• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* GENERATED SOURCE. DO NOT MODIFY. */
2 // © 2016 and later: Unicode, Inc. and others.
3 // License & terms of use: http://www.unicode.org/copyright.html#License
4 /*
5  *******************************************************************************
6  * Copyright (C) 1996-2015, International Business Machines
7  * Corporation and others.  All Rights Reserved.
8  *******************************************************************************
9  * CollationCompare.java, ported from collationcompare.h/.cpp
10  *
11  * C++ version created on: 2012feb14 with new and old collation code
12  * created by: Markus W. Scherer
13  */
14 
15 package ohos.global.icu.impl.coll;
16 
17 import ohos.global.icu.text.Collator;
18 
19 /**
20  * @hide exposed on OHOS
21  */
22 public final class CollationCompare /* all static */ {
compareUpToQuaternary(CollationIterator left, CollationIterator right, CollationSettings settings)23     public static int compareUpToQuaternary(CollationIterator left, CollationIterator right,
24             CollationSettings settings) {
25         int options = settings.options;
26         long variableTop;
27         if ((options & CollationSettings.ALTERNATE_MASK) == 0) {
28             variableTop = 0;
29         } else {
30             // +1 so that we can use "<" and primary ignorables test out early.
31             variableTop = settings.variableTop + 1;
32         }
33         boolean anyVariable = false;
34 
35         // Fetch CEs, compare primaries, store secondary & tertiary weights.
36         for (;;) {
37             // We fetch CEs until we get a non-ignorable primary or reach the end.
38             long leftPrimary;
39             do {
40                 long ce = left.nextCE();
41                 leftPrimary = ce >>> 32;
42                 if (leftPrimary < variableTop && leftPrimary > Collation.MERGE_SEPARATOR_PRIMARY) {
43                     // Variable CE, shift it to quaternary level.
44                     // Ignore all following primary ignorables, and shift further variable CEs.
45                     anyVariable = true;
46                     do {
47                         // Store only the primary of the variable CE.
48                         left.setCurrentCE(ce & 0xffffffff00000000L);
49                         for (;;) {
50                             ce = left.nextCE();
51                             leftPrimary = ce >>> 32;
52                             if (leftPrimary == 0) {
53                                 left.setCurrentCE(0);
54                             } else {
55                                 break;
56                             }
57                         }
58                     } while (leftPrimary < variableTop && leftPrimary > Collation.MERGE_SEPARATOR_PRIMARY);
59                 }
60             } while (leftPrimary == 0);
61 
62             long rightPrimary;
63             do {
64                 long ce = right.nextCE();
65                 rightPrimary = ce >>> 32;
66                 if (rightPrimary < variableTop && rightPrimary > Collation.MERGE_SEPARATOR_PRIMARY) {
67                     // Variable CE, shift it to quaternary level.
68                     // Ignore all following primary ignorables, and shift further variable CEs.
69                     anyVariable = true;
70                     do {
71                         // Store only the primary of the variable CE.
72                         right.setCurrentCE(ce & 0xffffffff00000000L);
73                         for (;;) {
74                             ce = right.nextCE();
75                             rightPrimary = ce >>> 32;
76                             if (rightPrimary == 0) {
77                                 right.setCurrentCE(0);
78                             } else {
79                                 break;
80                             }
81                         }
82                     } while (rightPrimary < variableTop && rightPrimary > Collation.MERGE_SEPARATOR_PRIMARY);
83                 }
84             } while (rightPrimary == 0);
85 
86             if (leftPrimary != rightPrimary) {
87                 // Return the primary difference, with script reordering.
88                 if (settings.hasReordering()) {
89                     leftPrimary = settings.reorder(leftPrimary);
90                     rightPrimary = settings.reorder(rightPrimary);
91                 }
92                 return (leftPrimary < rightPrimary) ? Collation.LESS : Collation.GREATER;
93             }
94             if (leftPrimary == Collation.NO_CE_PRIMARY) {
95                 break;
96             }
97         }
98 
99         // Compare the buffered secondary & tertiary weights.
100         // We might skip the secondary level but continue with the case level
101         // which is turned on separately.
102         if (CollationSettings.getStrength(options) >= Collator.SECONDARY) {
103             if ((options & CollationSettings.BACKWARD_SECONDARY) == 0) {
104                 int leftIndex = 0;
105                 int rightIndex = 0;
106                 for (;;) {
107                     int leftSecondary;
108                     do {
109                         leftSecondary = ((int) left.getCE(leftIndex++)) >>> 16;
110                     } while (leftSecondary == 0);
111 
112                     int rightSecondary;
113                     do {
114                         rightSecondary = ((int) right.getCE(rightIndex++)) >>> 16;
115                     } while (rightSecondary == 0);
116 
117                     if (leftSecondary != rightSecondary) {
118                         return (leftSecondary < rightSecondary) ? Collation.LESS : Collation.GREATER;
119                     }
120                     if (leftSecondary == Collation.NO_CE_WEIGHT16) {
121                         break;
122                     }
123                 }
124             } else {
125                 // The backwards secondary level compares secondary weights backwards
126                 // within segments separated by the merge separator (U+FFFE, weight 02).
127                 int leftStart = 0;
128                 int rightStart = 0;
129                 for (;;) {
130                     // Find the merge separator or the NO_CE terminator.
131                     long p;
132                     int leftLimit = leftStart;
133                     while ((p = left.getCE(leftLimit) >>> 32) > Collation.MERGE_SEPARATOR_PRIMARY
134                             || p == 0) {
135                         ++leftLimit;
136                     }
137                     int rightLimit = rightStart;
138                     while ((p = right.getCE(rightLimit) >>> 32) > Collation.MERGE_SEPARATOR_PRIMARY
139                             || p == 0) {
140                         ++rightLimit;
141                     }
142 
143                     // Compare the segments.
144                     int leftIndex = leftLimit;
145                     int rightIndex = rightLimit;
146                     for (;;) {
147                         int leftSecondary = 0;
148                         while (leftSecondary == 0 && leftIndex > leftStart) {
149                             leftSecondary = ((int) left.getCE(--leftIndex)) >>> 16;
150                         }
151 
152                         int rightSecondary = 0;
153                         while (rightSecondary == 0 && rightIndex > rightStart) {
154                             rightSecondary = ((int) right.getCE(--rightIndex)) >>> 16;
155                         }
156 
157                         if (leftSecondary != rightSecondary) {
158                             return (leftSecondary < rightSecondary) ? Collation.LESS : Collation.GREATER;
159                         }
160                         if (leftSecondary == 0) {
161                             break;
162                         }
163                     }
164 
165                     // Did we reach the end of either string?
166                     // Both strings have the same number of merge separators,
167                     // or else there would have been a primary-level difference.
168                     assert (left.getCE(leftLimit) == right.getCE(rightLimit));
169                     if (p == Collation.NO_CE_PRIMARY) {
170                         break;
171                     }
172                     // Skip both merge separators and continue.
173                     leftStart = leftLimit + 1;
174                     rightStart = rightLimit + 1;
175                 }
176             }
177         }
178 
179         if ((options & CollationSettings.CASE_LEVEL) != 0) {
180             int strength = CollationSettings.getStrength(options);
181             int leftIndex = 0;
182             int rightIndex = 0;
183             for (;;) {
184                 int leftCase, leftLower32, rightCase;
185                 if (strength == Collator.PRIMARY) {
186                     // Primary+caseLevel: Ignore case level weights of primary ignorables.
187                     // Otherwise we would get a-umlaut > a
188                     // which is not desirable for accent-insensitive sorting.
189                     // Check for (lower 32 bits) == 0 as well because variable CEs are stored
190                     // with only primary weights.
191                     long ce;
192                     do {
193                         ce = left.getCE(leftIndex++);
194                         leftCase = (int) ce;
195                     } while ((ce >>> 32) == 0 || leftCase == 0);
196                     leftLower32 = leftCase;
197                     leftCase &= 0xc000;
198 
199                     do {
200                         ce = right.getCE(rightIndex++);
201                         rightCase = (int) ce;
202                     } while ((ce >>> 32) == 0 || rightCase == 0);
203                     rightCase &= 0xc000;
204                 } else {
205                     // Secondary+caseLevel: By analogy with the above,
206                     // ignore case level weights of secondary ignorables.
207                     //
208                     // Note: A tertiary CE has uppercase case bits (0.0.ut)
209                     // to keep tertiary+caseFirst well-formed.
210                     //
211                     // Tertiary+caseLevel: Also ignore case level weights of secondary ignorables.
212                     // Otherwise a tertiary CE's uppercase would be no greater than
213                     // a primary/secondary CE's uppercase.
214                     // (See UCA well-formedness condition 2.)
215                     // We could construct a special case weight higher than uppercase,
216                     // but it's simpler to always ignore case weights of secondary ignorables,
217                     // turning 0.0.ut into 0.0.0.t.
218                     // (See LDML Collation, Case Parameters.)
219                     do {
220                         leftCase = (int) left.getCE(leftIndex++);
221                     } while ((leftCase & 0xffff0000) == 0);
222                     leftLower32 = leftCase;
223                     leftCase &= 0xc000;
224 
225                     do {
226                         rightCase = (int) right.getCE(rightIndex++);
227                     } while ((rightCase & 0xffff0000) == 0);
228                     rightCase &= 0xc000;
229                 }
230 
231                 // No need to handle NO_CE and MERGE_SEPARATOR specially:
232                 // There is one case weight for each previous-level weight,
233                 // so level length differences were handled there.
234                 if (leftCase != rightCase) {
235                     if ((options & CollationSettings.UPPER_FIRST) == 0) {
236                         return (leftCase < rightCase) ? Collation.LESS : Collation.GREATER;
237                     } else {
238                         return (leftCase < rightCase) ? Collation.GREATER : Collation.LESS;
239                     }
240                 }
241                 if ((leftLower32 >>> 16) == Collation.NO_CE_WEIGHT16) {
242                     break;
243                 }
244             }
245         }
246         if (CollationSettings.getStrength(options) <= Collator.SECONDARY) {
247             return Collation.EQUAL;
248         }
249 
250         int tertiaryMask = CollationSettings.getTertiaryMask(options);
251 
252         int leftIndex = 0;
253         int rightIndex = 0;
254         int anyQuaternaries = 0;
255         for (;;) {
256             int leftLower32, leftTertiary;
257             do {
258                 leftLower32 = (int) left.getCE(leftIndex++);
259                 anyQuaternaries |= leftLower32;
260                 assert ((leftLower32 & Collation.ONLY_TERTIARY_MASK) != 0 || (leftLower32 & 0xc0c0) == 0);
261                 leftTertiary = leftLower32 & tertiaryMask;
262             } while (leftTertiary == 0);
263 
264             int rightLower32, rightTertiary;
265             do {
266                 rightLower32 = (int) right.getCE(rightIndex++);
267                 anyQuaternaries |= rightLower32;
268                 assert ((rightLower32 & Collation.ONLY_TERTIARY_MASK) != 0 || (rightLower32 & 0xc0c0) == 0);
269                 rightTertiary = rightLower32 & tertiaryMask;
270             } while (rightTertiary == 0);
271 
272             if (leftTertiary != rightTertiary) {
273                 if (CollationSettings.sortsTertiaryUpperCaseFirst(options)) {
274                     // Pass through NO_CE and keep real tertiary weights larger than that.
275                     // Do not change the artificial uppercase weight of a tertiary CE (0.0.ut),
276                     // to keep tertiary CEs well-formed.
277                     // Their case+tertiary weights must be greater than those of
278                     // primary and secondary CEs.
279                     if (leftTertiary > Collation.NO_CE_WEIGHT16) {
280                         if ((leftLower32 & 0xffff0000) != 0) {
281                             leftTertiary ^= 0xc000;
282                         } else {
283                             leftTertiary += 0x4000;
284                         }
285                     }
286                     if (rightTertiary > Collation.NO_CE_WEIGHT16) {
287                         if ((rightLower32 & 0xffff0000) != 0) {
288                             rightTertiary ^= 0xc000;
289                         } else {
290                             rightTertiary += 0x4000;
291                         }
292                     }
293                 }
294                 return (leftTertiary < rightTertiary) ? Collation.LESS : Collation.GREATER;
295             }
296             if (leftTertiary == Collation.NO_CE_WEIGHT16) {
297                 break;
298             }
299         }
300         if (CollationSettings.getStrength(options) <= Collator.TERTIARY) {
301             return Collation.EQUAL;
302         }
303 
304         if (!anyVariable && (anyQuaternaries & 0xc0) == 0) {
305             // If there are no "variable" CEs and no non-zero quaternary weights,
306             // then there are no quaternary differences.
307             return Collation.EQUAL;
308         }
309 
310         leftIndex = 0;
311         rightIndex = 0;
312         for (;;) {
313             long leftQuaternary;
314             do {
315                 long ce = left.getCE(leftIndex++);
316                 leftQuaternary = ce & 0xffff;
317                 if (leftQuaternary <= Collation.NO_CE_WEIGHT16) {
318                     // Variable primary or completely ignorable or NO_CE.
319                     leftQuaternary = ce >>> 32;
320                 } else {
321                     // Regular CE, not tertiary ignorable.
322                     // Preserve the quaternary weight in bits 7..6.
323                     leftQuaternary |= 0xffffff3fL;
324                 }
325             } while (leftQuaternary == 0);
326 
327             long rightQuaternary;
328             do {
329                 long ce = right.getCE(rightIndex++);
330                 rightQuaternary = ce & 0xffff;
331                 if (rightQuaternary <= Collation.NO_CE_WEIGHT16) {
332                     // Variable primary or completely ignorable or NO_CE.
333                     rightQuaternary = ce >>> 32;
334                 } else {
335                     // Regular CE, not tertiary ignorable.
336                     // Preserve the quaternary weight in bits 7..6.
337                     rightQuaternary |= 0xffffff3fL;
338                 }
339             } while (rightQuaternary == 0);
340 
341             if (leftQuaternary != rightQuaternary) {
342                 // Return the difference, with script reordering.
343                 if (settings.hasReordering()) {
344                     leftQuaternary = settings.reorder(leftQuaternary);
345                     rightQuaternary = settings.reorder(rightQuaternary);
346                 }
347                 return (leftQuaternary < rightQuaternary) ? Collation.LESS : Collation.GREATER;
348             }
349             if (leftQuaternary == Collation.NO_CE_PRIMARY) {
350                 break;
351             }
352         }
353         return Collation.EQUAL;
354     }
355 }
356