+UBool PCEBuffer::isEmpty() const
+{
+ return bufferIndex <= 0;
+}
+
+void PCEBuffer::put(uint64_t ce, int32_t ixLow, int32_t ixHigh, UErrorCode &errorCode)
+{
+ if (U_FAILURE(errorCode)) {
+ return;
+ }
+ if (bufferIndex >= bufferSize) {
+ PCEI *newBuffer = NEW_ARRAY(PCEI, bufferSize + BUFFER_GROW);
+ if (newBuffer == NULL) {
+ errorCode = U_MEMORY_ALLOCATION_ERROR;
+ return;
+ }
+
+ ARRAY_COPY(newBuffer, buffer, bufferSize);
+
+ if (buffer != defaultBuffer) {
+ DELETE_ARRAY(buffer);
+ }
+
+ buffer = newBuffer;
+ bufferSize += BUFFER_GROW;
+ }
+
+ buffer[bufferIndex].ce = ce;
+ buffer[bufferIndex].low = ixLow;
+ buffer[bufferIndex].high = ixHigh;
+
+ bufferIndex += 1;
+}
+
+const PCEI *PCEBuffer::get()
+{
+ if (bufferIndex > 0) {
+ return &buffer[--bufferIndex];
+ }
+
+ return NULL;
+}
+
+UCollationPCE::UCollationPCE(UCollationElements *elems) { init(elems); }
+
+UCollationPCE::UCollationPCE(CollationElementIterator *iter) { init(iter); }
+
+void UCollationPCE::init(UCollationElements *elems) {
+ init(CollationElementIterator::fromUCollationElements(elems));
+}
+
+void UCollationPCE::init(CollationElementIterator *iter)
+{
+ cei = iter;
+ init(*iter->rbc_);
+}
+
+void UCollationPCE::init(const Collator &coll)
+{
+ UErrorCode status = U_ZERO_ERROR;
+
+ strength = coll.getAttribute(UCOL_STRENGTH, status);
+ toShift = coll.getAttribute(UCOL_ALTERNATE_HANDLING, status) == UCOL_SHIFTED;
+ isShifted = FALSE;
+ variableTop = coll.getVariableTop(status);
+}
+
+UCollationPCE::~UCollationPCE()
+{
+ // nothing to do
+}
+
+uint64_t UCollationPCE::processCE(uint32_t ce)
+{
+ uint64_t primary = 0, secondary = 0, tertiary = 0, quaternary = 0;
+
+ // This is clean, but somewhat slow...
+ // We could apply the mask to ce and then
+ // just get all three orders...
+ switch(strength) {
+ default:
+ tertiary = ucol_tertiaryOrder(ce);
+ U_FALLTHROUGH;
+
+ case UCOL_SECONDARY:
+ secondary = ucol_secondaryOrder(ce);
+ U_FALLTHROUGH;
+
+ case UCOL_PRIMARY:
+ primary = ucol_primaryOrder(ce);
+ }
+
+ // **** This should probably handle continuations too. ****
+ // **** That means that we need 24 bits for the primary ****
+ // **** instead of the 16 that we're currently using. ****
+ // **** So we can lay out the 64 bits as: 24.12.12.16. ****
+ // **** Another complication with continuations is that ****
+ // **** the *second* CE is marked as a continuation, so ****
+ // **** we always have to peek ahead to know how long ****
+ // **** the primary is... ****
+ if ((toShift && variableTop > ce && primary != 0)
+ || (isShifted && primary == 0)) {
+
+ if (primary == 0) {
+ return UCOL_IGNORABLE;
+ }
+
+ if (strength >= UCOL_QUATERNARY) {
+ quaternary = primary;
+ }
+
+ primary = secondary = tertiary = 0;
+ isShifted = TRUE;
+ } else {
+ if (strength >= UCOL_QUATERNARY) {
+ quaternary = 0xFFFF;
+ }
+
+ isShifted = FALSE;
+ }
+
+ return primary << 48 | secondary << 32 | tertiary << 16 | quaternary;
+}
+
+U_NAMESPACE_END
+
+/* public methods ---------------------------------------------------- */