int32_t ChoiceFormat::findSubMessage(const MessagePattern &pattern, int32_t partIndex, double number) { int32_t count = pattern.countParts(); int32_t msgStart; // Iterate over (ARG_INT|DOUBLE, ARG_SELECTOR, message) tuples // until ARG_LIMIT or end of choice-only pattern. // Ignore the first number and selector and start the loop on the first message. partIndex += 2; for (;;) { // Skip but remember the current sub-message. msgStart = partIndex; partIndex = pattern.getLimitPartIndex(partIndex); if (++partIndex >= count) { // Reached the end of the choice-only pattern. // Return with the last sub-message. break; } const MessagePattern::Part &part = pattern.getPart(partIndex++); UMessagePatternPartType type = part.getType(); if (type == UMSGPAT_PART_TYPE_ARG_LIMIT) { // Reached the end of the ChoiceFormat style. // Return with the last sub-message. break; } // part is an ARG_INT or ARG_DOUBLE U_ASSERT(MessagePattern::Part::hasNumericValue(type)); double boundary = pattern.getNumericValue(part); // Fetch the ARG_SELECTOR character. int32_t selectorIndex = pattern.getPatternIndex(partIndex++); UChar boundaryChar = pattern.getPatternString().charAt(selectorIndex); if (boundaryChar == LESS_THAN ? !(number > boundary) : !(number >= boundary)) { // The number is in the interval between the previous boundary and the current one. // Return with the sub-message between them. // The !(a>b) and !(a>=b) comparisons are equivalent to // (a<=b) and (a<b) except they "catch" NaN. break; } } return msgStart; }