LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - plurfmt.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 300 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : // © 2016 and later: Unicode, Inc. and others.
       2             : // License & terms of use: http://www.unicode.org/copyright.html
       3             : /*
       4             : *******************************************************************************
       5             : * Copyright (C) 2009-2015, International Business Machines Corporation and
       6             : * others. All Rights Reserved.
       7             : *******************************************************************************
       8             : *
       9             : * File PLURFMT.CPP
      10             : *******************************************************************************
      11             : */
      12             : 
      13             : #include "unicode/decimfmt.h"
      14             : #include "unicode/messagepattern.h"
      15             : #include "unicode/plurfmt.h"
      16             : #include "unicode/plurrule.h"
      17             : #include "unicode/utypes.h"
      18             : #include "cmemory.h"
      19             : #include "messageimpl.h"
      20             : #include "nfrule.h"
      21             : #include "plurrule_impl.h"
      22             : #include "uassert.h"
      23             : #include "uhash.h"
      24             : #include "precision.h"
      25             : #include "visibledigits.h"
      26             : 
      27             : #if !UCONFIG_NO_FORMATTING
      28             : 
      29             : U_NAMESPACE_BEGIN
      30             : 
      31             : static const UChar OTHER_STRING[] = {
      32             :     0x6F, 0x74, 0x68, 0x65, 0x72, 0  // "other"
      33             : };
      34             : 
      35           0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(PluralFormat)
      36             : 
      37           0 : PluralFormat::PluralFormat(UErrorCode& status)
      38             :         : locale(Locale::getDefault()),
      39             :           msgPattern(status),
      40             :           numberFormat(NULL),
      41           0 :           offset(0) {
      42           0 :     init(NULL, UPLURAL_TYPE_CARDINAL, status);
      43           0 : }
      44             : 
      45           0 : PluralFormat::PluralFormat(const Locale& loc, UErrorCode& status)
      46             :         : locale(loc),
      47             :           msgPattern(status),
      48             :           numberFormat(NULL),
      49           0 :           offset(0) {
      50           0 :     init(NULL, UPLURAL_TYPE_CARDINAL, status);
      51           0 : }
      52             : 
      53           0 : PluralFormat::PluralFormat(const PluralRules& rules, UErrorCode& status)
      54             :         : locale(Locale::getDefault()),
      55             :           msgPattern(status),
      56             :           numberFormat(NULL),
      57           0 :           offset(0) {
      58           0 :     init(&rules, UPLURAL_TYPE_COUNT, status);
      59           0 : }
      60             : 
      61           0 : PluralFormat::PluralFormat(const Locale& loc,
      62             :                            const PluralRules& rules,
      63           0 :                            UErrorCode& status)
      64             :         : locale(loc),
      65             :           msgPattern(status),
      66             :           numberFormat(NULL),
      67           0 :           offset(0) {
      68           0 :     init(&rules, UPLURAL_TYPE_COUNT, status);
      69           0 : }
      70             : 
      71           0 : PluralFormat::PluralFormat(const Locale& loc,
      72             :                            UPluralType type,
      73           0 :                            UErrorCode& status)
      74             :         : locale(loc),
      75             :           msgPattern(status),
      76             :           numberFormat(NULL),
      77           0 :           offset(0) {
      78           0 :     init(NULL, type, status);
      79           0 : }
      80             : 
      81           0 : PluralFormat::PluralFormat(const UnicodeString& pat,
      82           0 :                            UErrorCode& status)
      83             :         : locale(Locale::getDefault()),
      84             :           msgPattern(status),
      85             :           numberFormat(NULL),
      86           0 :           offset(0) {
      87           0 :     init(NULL, UPLURAL_TYPE_CARDINAL, status);
      88           0 :     applyPattern(pat, status);
      89           0 : }
      90             : 
      91           0 : PluralFormat::PluralFormat(const Locale& loc,
      92             :                            const UnicodeString& pat,
      93           0 :                            UErrorCode& status)
      94             :         : locale(loc),
      95             :           msgPattern(status),
      96             :           numberFormat(NULL),
      97           0 :           offset(0) {
      98           0 :     init(NULL, UPLURAL_TYPE_CARDINAL, status);
      99           0 :     applyPattern(pat, status);
     100           0 : }
     101             : 
     102           0 : PluralFormat::PluralFormat(const PluralRules& rules,
     103             :                            const UnicodeString& pat,
     104           0 :                            UErrorCode& status)
     105             :         : locale(Locale::getDefault()),
     106             :           msgPattern(status),
     107             :           numberFormat(NULL),
     108           0 :           offset(0) {
     109           0 :     init(&rules, UPLURAL_TYPE_COUNT, status);
     110           0 :     applyPattern(pat, status);
     111           0 : }
     112             : 
     113           0 : PluralFormat::PluralFormat(const Locale& loc,
     114             :                            const PluralRules& rules,
     115             :                            const UnicodeString& pat,
     116           0 :                            UErrorCode& status)
     117             :         : locale(loc),
     118             :           msgPattern(status),
     119             :           numberFormat(NULL),
     120           0 :           offset(0) {
     121           0 :     init(&rules, UPLURAL_TYPE_COUNT, status);
     122           0 :     applyPattern(pat, status);
     123           0 : }
     124             : 
     125           0 : PluralFormat::PluralFormat(const Locale& loc,
     126             :                            UPluralType type,
     127             :                            const UnicodeString& pat,
     128           0 :                            UErrorCode& status)
     129             :         : locale(loc),
     130             :           msgPattern(status),
     131             :           numberFormat(NULL),
     132           0 :           offset(0) {
     133           0 :     init(NULL, type, status);
     134           0 :     applyPattern(pat, status);
     135           0 : }
     136             : 
     137           0 : PluralFormat::PluralFormat(const PluralFormat& other)
     138             :         : Format(other),
     139             :           locale(other.locale),
     140             :           msgPattern(other.msgPattern),
     141             :           numberFormat(NULL),
     142           0 :           offset(other.offset) {
     143           0 :     copyObjects(other);
     144           0 : }
     145             : 
     146             : void
     147           0 : PluralFormat::copyObjects(const PluralFormat& other) {
     148           0 :     UErrorCode status = U_ZERO_ERROR;
     149           0 :     if (numberFormat != NULL) {
     150           0 :         delete numberFormat;
     151             :     }
     152           0 :     if (pluralRulesWrapper.pluralRules != NULL) {
     153           0 :         delete pluralRulesWrapper.pluralRules;
     154             :     }
     155             : 
     156           0 :     if (other.numberFormat == NULL) {
     157           0 :         numberFormat = NumberFormat::createInstance(locale, status);
     158             :     } else {
     159           0 :         numberFormat = (NumberFormat*)other.numberFormat->clone();
     160             :     }
     161           0 :     if (other.pluralRulesWrapper.pluralRules == NULL) {
     162           0 :         pluralRulesWrapper.pluralRules = PluralRules::forLocale(locale, status);
     163             :     } else {
     164           0 :         pluralRulesWrapper.pluralRules = other.pluralRulesWrapper.pluralRules->clone();
     165             :     }
     166           0 : }
     167             : 
     168             : 
     169           0 : PluralFormat::~PluralFormat() {
     170           0 :     delete numberFormat;
     171           0 : }
     172             : 
     173             : void
     174           0 : PluralFormat::init(const PluralRules* rules, UPluralType type, UErrorCode& status) {
     175           0 :     if (U_FAILURE(status)) {
     176           0 :         return;
     177             :     }
     178             : 
     179           0 :     if (rules==NULL) {
     180           0 :         pluralRulesWrapper.pluralRules = PluralRules::forLocale(locale, type, status);
     181             :     } else {
     182           0 :         pluralRulesWrapper.pluralRules = rules->clone();
     183           0 :         if (pluralRulesWrapper.pluralRules == NULL) {
     184           0 :             status = U_MEMORY_ALLOCATION_ERROR;
     185           0 :             return;
     186             :         }
     187             :     }
     188             : 
     189           0 :     numberFormat= NumberFormat::createInstance(locale, status);
     190             : }
     191             : 
     192             : void
     193           0 : PluralFormat::applyPattern(const UnicodeString& newPattern, UErrorCode& status) {
     194           0 :     msgPattern.parsePluralStyle(newPattern, NULL, status);
     195           0 :     if (U_FAILURE(status)) {
     196           0 :         msgPattern.clear();
     197           0 :         offset = 0;
     198           0 :         return;
     199             :     }
     200           0 :     offset = msgPattern.getPluralOffset(0);
     201             : }
     202             : 
     203             : UnicodeString&
     204           0 : PluralFormat::format(const Formattable& obj,
     205             :                    UnicodeString& appendTo,
     206             :                    FieldPosition& pos,
     207             :                    UErrorCode& status) const
     208             : {
     209           0 :     if (U_FAILURE(status)) return appendTo;
     210             : 
     211           0 :     if (obj.isNumeric()) {
     212           0 :         return format(obj, obj.getDouble(), appendTo, pos, status);
     213             :     } else {
     214           0 :         status = U_ILLEGAL_ARGUMENT_ERROR;
     215           0 :         return appendTo;
     216             :     }
     217             : }
     218             : 
     219             : UnicodeString
     220           0 : PluralFormat::format(int32_t number, UErrorCode& status) const {
     221           0 :     FieldPosition fpos(FieldPosition::DONT_CARE);
     222           0 :     UnicodeString result;
     223           0 :     return format(Formattable(number), number, result, fpos, status);
     224             : }
     225             : 
     226             : UnicodeString
     227           0 : PluralFormat::format(double number, UErrorCode& status) const {
     228           0 :     FieldPosition fpos(FieldPosition::DONT_CARE);
     229           0 :     UnicodeString result;
     230           0 :     return format(Formattable(number), number, result, fpos, status);
     231             : }
     232             : 
     233             : 
     234             : UnicodeString&
     235           0 : PluralFormat::format(int32_t number,
     236             :                      UnicodeString& appendTo,
     237             :                      FieldPosition& pos,
     238             :                      UErrorCode& status) const {
     239           0 :     return format(Formattable(number), (double)number, appendTo, pos, status);
     240             : }
     241             : 
     242             : UnicodeString&
     243           0 : PluralFormat::format(double number,
     244             :                      UnicodeString& appendTo,
     245             :                      FieldPosition& pos,
     246             :                      UErrorCode& status) const {
     247           0 :     return format(Formattable(number), (double)number, appendTo, pos, status);
     248             : }
     249             : 
     250             : UnicodeString&
     251           0 : PluralFormat::format(const Formattable& numberObject, double number,
     252             :                      UnicodeString& appendTo,
     253             :                      FieldPosition& pos,
     254             :                      UErrorCode& status) const {
     255           0 :     if (U_FAILURE(status)) {
     256           0 :         return appendTo;
     257             :     }
     258           0 :     if (msgPattern.countParts() == 0) {
     259           0 :         return numberFormat->format(numberObject, appendTo, pos, status);
     260             :     }
     261             :     // Get the appropriate sub-message.
     262             :     // Select it based on the formatted number-offset.
     263           0 :     double numberMinusOffset = number - offset;
     264           0 :     UnicodeString numberString;
     265           0 :     FieldPosition ignorePos;
     266           0 :     FixedPrecision fp;
     267           0 :     VisibleDigitsWithExponent dec;
     268           0 :     fp.initVisibleDigitsWithExponent(numberMinusOffset, dec, status);
     269           0 :     if (U_FAILURE(status)) {
     270           0 :         return appendTo;
     271             :     }
     272           0 :     if (offset == 0) {
     273           0 :         DecimalFormat *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
     274           0 :         if(decFmt != NULL) {
     275             :             decFmt->initVisibleDigitsWithExponent(
     276           0 :                     numberObject, dec, status);
     277           0 :             if (U_FAILURE(status)) {
     278           0 :                 return appendTo;
     279             :             }
     280           0 :             decFmt->format(dec, numberString, ignorePos, status);
     281             :         } else {
     282           0 :             numberFormat->format(
     283           0 :                     numberObject, numberString, ignorePos, status);  // could be BigDecimal etc.
     284             :         }
     285             :     } else {
     286           0 :         DecimalFormat *decFmt = dynamic_cast<DecimalFormat *>(numberFormat);
     287           0 :         if(decFmt != NULL) {
     288             :             decFmt->initVisibleDigitsWithExponent(
     289           0 :                     numberMinusOffset, dec, status);
     290           0 :             if (U_FAILURE(status)) {
     291           0 :                 return appendTo;
     292             :             }
     293           0 :             decFmt->format(dec, numberString, ignorePos, status);
     294             :         } else {
     295           0 :             numberFormat->format(
     296           0 :                     numberMinusOffset, numberString, ignorePos, status);
     297             :         }
     298             :     }
     299           0 :     int32_t partIndex = findSubMessage(msgPattern, 0, pluralRulesWrapper, &dec, number, status);
     300           0 :     if (U_FAILURE(status)) { return appendTo; }
     301             :     // Replace syntactic # signs in the top level of this sub-message
     302             :     // (not in nested arguments) with the formatted number-offset.
     303           0 :     const UnicodeString& pattern = msgPattern.getPatternString();
     304           0 :     int32_t prevIndex = msgPattern.getPart(partIndex).getLimit();
     305             :     for (;;) {
     306           0 :         const MessagePattern::Part& part = msgPattern.getPart(++partIndex);
     307           0 :         const UMessagePatternPartType type = part.getType();
     308           0 :         int32_t index = part.getIndex();
     309           0 :         if (type == UMSGPAT_PART_TYPE_MSG_LIMIT) {
     310           0 :             return appendTo.append(pattern, prevIndex, index - prevIndex);
     311           0 :         } else if ((type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) ||
     312           0 :             (type == UMSGPAT_PART_TYPE_SKIP_SYNTAX && MessageImpl::jdkAposMode(msgPattern))) {
     313           0 :             appendTo.append(pattern, prevIndex, index - prevIndex);
     314           0 :             if (type == UMSGPAT_PART_TYPE_REPLACE_NUMBER) {
     315           0 :                 appendTo.append(numberString);
     316             :             }
     317           0 :             prevIndex = part.getLimit();
     318           0 :         } else if (type == UMSGPAT_PART_TYPE_ARG_START) {
     319           0 :             appendTo.append(pattern, prevIndex, index - prevIndex);
     320           0 :             prevIndex = index;
     321           0 :             partIndex = msgPattern.getLimitPartIndex(partIndex);
     322           0 :             index = msgPattern.getPart(partIndex).getLimit();
     323           0 :             MessageImpl::appendReducedApostrophes(pattern, prevIndex, index, appendTo);
     324           0 :             prevIndex = index;
     325             :         }
     326           0 :     }
     327             : }
     328             : 
     329             : UnicodeString&
     330           0 : PluralFormat::toPattern(UnicodeString& appendTo) {
     331           0 :     if (0 == msgPattern.countParts()) {
     332           0 :         appendTo.setToBogus();
     333             :     } else {
     334           0 :         appendTo.append(msgPattern.getPatternString());
     335             :     }
     336           0 :     return appendTo;
     337             : }
     338             : 
     339             : void
     340           0 : PluralFormat::setLocale(const Locale& loc, UErrorCode& status) {
     341           0 :     if (U_FAILURE(status)) {
     342           0 :         return;
     343             :     }
     344           0 :     locale = loc;
     345           0 :     msgPattern.clear();
     346           0 :     delete numberFormat;
     347           0 :     offset = 0;
     348           0 :     numberFormat = NULL;
     349           0 :     pluralRulesWrapper.reset();
     350           0 :     init(NULL, UPLURAL_TYPE_CARDINAL, status);
     351             : }
     352             : 
     353             : void
     354           0 : PluralFormat::setNumberFormat(const NumberFormat* format, UErrorCode& status) {
     355           0 :     if (U_FAILURE(status)) {
     356           0 :         return;
     357             :     }
     358           0 :     NumberFormat* nf = (NumberFormat*)format->clone();
     359           0 :     if (nf != NULL) {
     360           0 :         delete numberFormat;
     361           0 :         numberFormat = nf;
     362             :     } else {
     363           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     364             :     }
     365             : }
     366             : 
     367             : Format*
     368           0 : PluralFormat::clone() const
     369             : {
     370           0 :     return new PluralFormat(*this);
     371             : }
     372             : 
     373             : 
     374             : PluralFormat&
     375           0 : PluralFormat::operator=(const PluralFormat& other) {
     376           0 :     if (this != &other) {
     377           0 :         locale = other.locale;
     378           0 :         msgPattern = other.msgPattern;
     379           0 :         offset = other.offset;
     380           0 :         copyObjects(other);
     381             :     }
     382             : 
     383           0 :     return *this;
     384             : }
     385             : 
     386             : UBool
     387           0 : PluralFormat::operator==(const Format& other) const {
     388           0 :     if (this == &other) {
     389           0 :         return TRUE;
     390             :     }
     391           0 :     if (!Format::operator==(other)) {
     392           0 :         return FALSE;
     393             :     }
     394           0 :     const PluralFormat& o = (const PluralFormat&)other;
     395             :     return
     396           0 :         locale == o.locale &&
     397           0 :         msgPattern == o.msgPattern &&  // implies same offset
     398           0 :         (numberFormat == NULL) == (o.numberFormat == NULL) &&
     399           0 :         (numberFormat == NULL || *numberFormat == *o.numberFormat) &&
     400           0 :         (pluralRulesWrapper.pluralRules == NULL) == (o.pluralRulesWrapper.pluralRules == NULL) &&
     401           0 :         (pluralRulesWrapper.pluralRules == NULL ||
     402           0 :             *pluralRulesWrapper.pluralRules == *o.pluralRulesWrapper.pluralRules);
     403             : }
     404             : 
     405             : UBool
     406           0 : PluralFormat::operator!=(const Format& other) const {
     407           0 :     return  !operator==(other);
     408             : }
     409             : 
     410             : void
     411           0 : PluralFormat::parseObject(const UnicodeString& /*source*/,
     412             :                         Formattable& /*result*/,
     413             :                         ParsePosition& pos) const
     414             : {
     415             :     // Parsing not supported.
     416           0 :     pos.setErrorIndex(pos.getIndex());
     417           0 : }
     418             : 
     419           0 : int32_t PluralFormat::findSubMessage(const MessagePattern& pattern, int32_t partIndex,
     420             :                                      const PluralSelector& selector, void *context,
     421             :                                      double number, UErrorCode& ec) {
     422           0 :     if (U_FAILURE(ec)) {
     423           0 :         return 0;
     424             :     }
     425           0 :     int32_t count=pattern.countParts();
     426             :     double offset;
     427           0 :     const MessagePattern::Part* part=&pattern.getPart(partIndex);
     428           0 :     if (MessagePattern::Part::hasNumericValue(part->getType())) {
     429           0 :         offset=pattern.getNumericValue(*part);
     430           0 :         ++partIndex;
     431             :     } else {
     432           0 :         offset=0;
     433             :     }
     434             :     // The keyword is empty until we need to match against a non-explicit, not-"other" value.
     435             :     // Then we get the keyword from the selector.
     436             :     // (In other words, we never call the selector if we match against an explicit value,
     437             :     // or if the only non-explicit keyword is "other".)
     438           0 :     UnicodeString keyword;
     439           0 :     UnicodeString other(FALSE, OTHER_STRING, 5);
     440             :     // When we find a match, we set msgStart>0 and also set this boolean to true
     441             :     // to avoid matching the keyword again (duplicates are allowed)
     442             :     // while we continue to look for an explicit-value match.
     443           0 :     UBool haveKeywordMatch=FALSE;
     444             :     // msgStart is 0 until we find any appropriate sub-message.
     445             :     // We remember the first "other" sub-message if we have not seen any
     446             :     // appropriate sub-message before.
     447             :     // We remember the first matching-keyword sub-message if we have not seen
     448             :     // one of those before.
     449             :     // (The parser allows [does not check for] duplicate keywords.
     450             :     // We just have to make sure to take the first one.)
     451             :     // We avoid matching the keyword twice by also setting haveKeywordMatch=true
     452             :     // at the first keyword match.
     453             :     // We keep going until we find an explicit-value match or reach the end of the plural style.
     454           0 :     int32_t msgStart=0;
     455             :     // Iterate over (ARG_SELECTOR [ARG_INT|ARG_DOUBLE] message) tuples
     456             :     // until ARG_LIMIT or end of plural-only pattern.
     457           0 :     do {
     458           0 :         part=&pattern.getPart(partIndex++);
     459           0 :         const UMessagePatternPartType type = part->getType();
     460           0 :         if(type==UMSGPAT_PART_TYPE_ARG_LIMIT) {
     461           0 :             break;
     462             :         }
     463           0 :         U_ASSERT (type==UMSGPAT_PART_TYPE_ARG_SELECTOR);
     464             :         // part is an ARG_SELECTOR followed by an optional explicit value, and then a message
     465           0 :         if(MessagePattern::Part::hasNumericValue(pattern.getPartType(partIndex))) {
     466             :             // explicit value like "=2"
     467           0 :             part=&pattern.getPart(partIndex++);
     468           0 :             if(number==pattern.getNumericValue(*part)) {
     469             :                 // matches explicit value
     470           0 :                 return partIndex;
     471             :             }
     472           0 :         } else if(!haveKeywordMatch) {
     473             :             // plural keyword like "few" or "other"
     474             :             // Compare "other" first and call the selector if this is not "other".
     475           0 :             if(pattern.partSubstringMatches(*part, other)) {
     476           0 :                 if(msgStart==0) {
     477           0 :                     msgStart=partIndex;
     478           0 :                     if(0 == keyword.compare(other)) {
     479             :                         // This is the first "other" sub-message,
     480             :                         // and the selected keyword is also "other".
     481             :                         // Do not match "other" again.
     482           0 :                         haveKeywordMatch=TRUE;
     483             :                     }
     484             :                 }
     485             :             } else {
     486           0 :                 if(keyword.isEmpty()) {
     487           0 :                     keyword=selector.select(context, number-offset, ec);
     488           0 :                     if(msgStart!=0 && (0 == keyword.compare(other))) {
     489             :                         // We have already seen an "other" sub-message.
     490             :                         // Do not match "other" again.
     491           0 :                         haveKeywordMatch=TRUE;
     492             :                         // Skip keyword matching but do getLimitPartIndex().
     493             :                     }
     494             :                 }
     495           0 :                 if(!haveKeywordMatch && pattern.partSubstringMatches(*part, keyword)) {
     496             :                     // keyword matches
     497           0 :                     msgStart=partIndex;
     498             :                     // Do not match this keyword again.
     499           0 :                     haveKeywordMatch=TRUE;
     500             :                 }
     501             :             }
     502             :         }
     503           0 :         partIndex=pattern.getLimitPartIndex(partIndex);
     504             :     } while(++partIndex<count);
     505           0 :     return msgStart;
     506             : }
     507             : 
     508           0 : void PluralFormat::parseType(const UnicodeString& source, const NFRule *rbnfLenientScanner, Formattable& result, FieldPosition& pos) const {
     509             :     // If no pattern was applied, return null.
     510           0 :     if (msgPattern.countParts() == 0) {
     511           0 :         pos.setBeginIndex(-1);
     512           0 :         pos.setEndIndex(-1);
     513           0 :         return;
     514             :     }
     515           0 :     int partIndex = 0;
     516             :     int currMatchIndex;
     517           0 :     int count=msgPattern.countParts();
     518           0 :     int startingAt = pos.getBeginIndex();
     519           0 :     if (startingAt < 0) {
     520           0 :         startingAt = 0;
     521             :     }
     522             : 
     523             :     // The keyword is null until we need to match against a non-explicit, not-"other" value.
     524             :     // Then we get the keyword from the selector.
     525             :     // (In other words, we never call the selector if we match against an explicit value,
     526             :     // or if the only non-explicit keyword is "other".)
     527           0 :     UnicodeString keyword;
     528           0 :     UnicodeString matchedWord;
     529           0 :     const UnicodeString& pattern = msgPattern.getPatternString();
     530           0 :     int matchedIndex = -1;
     531             :     // Iterate over (ARG_SELECTOR ARG_START message ARG_LIMIT) tuples
     532             :     // until the end of the plural-only pattern.
     533           0 :     while (partIndex < count) {
     534           0 :         const MessagePattern::Part* partSelector = &msgPattern.getPart(partIndex++);
     535           0 :         if (partSelector->getType() != UMSGPAT_PART_TYPE_ARG_SELECTOR) {
     536             :             // Bad format
     537           0 :             continue;
     538             :         }
     539             : 
     540           0 :         const MessagePattern::Part* partStart = &msgPattern.getPart(partIndex++);
     541           0 :         if (partStart->getType() != UMSGPAT_PART_TYPE_MSG_START) {
     542             :             // Bad format
     543           0 :             continue;
     544             :         }
     545             : 
     546           0 :         const MessagePattern::Part* partLimit = &msgPattern.getPart(partIndex++);
     547           0 :         if (partLimit->getType() != UMSGPAT_PART_TYPE_MSG_LIMIT) {
     548             :             // Bad format
     549           0 :             continue;
     550             :         }
     551             : 
     552           0 :         UnicodeString currArg = pattern.tempSubString(partStart->getLimit(), partLimit->getIndex() - partStart->getLimit());
     553           0 :         if (rbnfLenientScanner != NULL) {
     554             :             // If lenient parsing is turned ON, we've got some time consuming parsing ahead of us.
     555           0 :             int32_t length = -1;
     556           0 :             currMatchIndex = rbnfLenientScanner->findTextLenient(source, currArg, startingAt, &length);
     557             :         }
     558             :         else {
     559           0 :             currMatchIndex = source.indexOf(currArg, startingAt);
     560             :         }
     561           0 :         if (currMatchIndex >= 0 && currMatchIndex >= matchedIndex && currArg.length() > matchedWord.length()) {
     562           0 :             matchedIndex = currMatchIndex;
     563           0 :             matchedWord = currArg;
     564           0 :             keyword = pattern.tempSubString(partStart->getLimit(), partLimit->getIndex() - partStart->getLimit());
     565             :         }
     566             :     }
     567           0 :     if (matchedIndex >= 0) {
     568           0 :         pos.setBeginIndex(matchedIndex);
     569           0 :         pos.setEndIndex(matchedIndex + matchedWord.length());
     570           0 :         result.setString(keyword);
     571           0 :         return;
     572             :     }
     573             : 
     574             :     // Not found!
     575           0 :     pos.setBeginIndex(-1);
     576           0 :     pos.setEndIndex(-1);
     577             : }
     578             : 
     579           0 : PluralFormat::PluralSelector::~PluralSelector() {}
     580             : 
     581           0 : PluralFormat::PluralSelectorAdapter::~PluralSelectorAdapter() {
     582           0 :     delete pluralRules;
     583           0 : }
     584             : 
     585           0 : UnicodeString PluralFormat::PluralSelectorAdapter::select(void *context, double number,
     586             :                                                           UErrorCode& /*ec*/) const {
     587             :     (void)number;  // unused except in the assertion
     588           0 :     VisibleDigitsWithExponent *dec=static_cast<VisibleDigitsWithExponent *>(context);
     589           0 :     return pluralRules->select(*dec);
     590             : }
     591             : 
     592           0 : void PluralFormat::PluralSelectorAdapter::reset() {
     593           0 :     delete pluralRules;
     594           0 :     pluralRules = NULL;
     595           0 : }
     596             : 
     597             : 
     598             : U_NAMESPACE_END
     599             : 
     600             : 
     601             : #endif /* #if !UCONFIG_NO_FORMATTING */
     602             : 
     603             : //eof

Generated by: LCOV version 1.13