LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - affixpatternparser.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 392 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 30 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             :  * Copyright (C) 2015, International Business Machines
       5             :  * Corporation and others.  All Rights Reserved.
       6             :  *
       7             :  * file name: affixpatternparser.cpp
       8             :  */
       9             : 
      10             : #include "unicode/utypes.h"
      11             : 
      12             : #if !UCONFIG_NO_FORMATTING
      13             : 
      14             : #include "unicode/dcfmtsym.h"
      15             : #include "unicode/plurrule.h"
      16             : #include "unicode/strenum.h"
      17             : #include "unicode/ucurr.h"
      18             : #include "unicode/ustring.h"
      19             : #include "affixpatternparser.h"
      20             : #include "charstr.h"
      21             : #include "precision.h"
      22             : #include "uassert.h"
      23             : #include "unistrappender.h"
      24             : 
      25             :         static UChar gDefaultSymbols[] = {0xa4, 0xa4, 0xa4};
      26             : 
      27             : static UChar gPercent = 0x25;
      28             : static UChar gPerMill = 0x2030;
      29             : static UChar gNegative = 0x2D;
      30             : static UChar gPositive = 0x2B;
      31             : 
      32             : #define PACK_TOKEN_AND_LENGTH(t, l) ((UChar) (((t) << 8) | (l & 0xFF)))
      33             : 
      34             : #define UNPACK_TOKEN(c) ((AffixPattern::ETokenType) (((c) >> 8) & 0x7F))
      35             : 
      36             : #define UNPACK_LONG(c) (((c) >> 8) & 0x80)
      37             : 
      38             : #define UNPACK_LENGTH(c) ((c) & 0xFF)
      39             : 
      40             : U_NAMESPACE_BEGIN
      41             : 
      42             : static int32_t
      43           0 : nextToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) {
      44           0 :     if (buffer[idx] != 0x27 || idx + 1 == len) {
      45           0 :         *token = buffer[idx];
      46           0 :         return 1;
      47             :     }
      48           0 :     *token = buffer[idx + 1];
      49           0 :     if (buffer[idx + 1] == 0xA4) {
      50           0 :         int32_t i = 2;
      51           0 :         for (; idx + i < len && i < 4 && buffer[idx + i] == buffer[idx + 1]; ++i)
      52             :           ;
      53           0 :         return i;
      54             :     }
      55           0 :     return 2;
      56             : }
      57             : 
      58             : static int32_t
      59           0 : nextUserToken(const UChar *buffer, int32_t idx, int32_t len, UChar *token) {
      60           0 :     *token = buffer[idx];
      61             :     int32_t max;
      62           0 :     switch (buffer[idx]) {
      63             :     case 0x27:
      64           0 :         max = 2;
      65           0 :         break;
      66             :     case 0xA4:
      67           0 :         max = 3;
      68           0 :         break;
      69             :     default:
      70           0 :         max = 1;
      71           0 :         break;
      72             :     }
      73           0 :     int32_t i = 1;
      74           0 :     for (; idx + i < len && i < max && buffer[idx + i] == buffer[idx]; ++i)
      75             :       ;
      76           0 :     return i;
      77             : }
      78             : 
      79           0 : CurrencyAffixInfo::CurrencyAffixInfo()
      80             :         : fSymbol(gDefaultSymbols, 1),
      81             :           fISO(gDefaultSymbols, 2),
      82           0 :           fLong(DigitAffix(gDefaultSymbols, 3)),
      83           0 :           fIsDefault(TRUE) {
      84           0 : }
      85             : 
      86             : void
      87           0 : CurrencyAffixInfo::set(
      88             :         const char *locale,
      89             :         const PluralRules *rules,
      90             :         const UChar *currency,
      91             :         UErrorCode &status) {
      92           0 :     if (U_FAILURE(status)) {
      93           0 :         return;
      94             :     }
      95           0 :     fIsDefault = FALSE;
      96           0 :     if (currency == NULL) {
      97           0 :         fSymbol.setTo(gDefaultSymbols, 1);
      98           0 :         fISO.setTo(gDefaultSymbols, 2);
      99           0 :         fLong.remove();
     100           0 :         fLong.append(gDefaultSymbols, 3);
     101           0 :         fIsDefault = TRUE;
     102           0 :         return;
     103             :     }
     104             :     int32_t len;
     105             :     UBool unusedIsChoice;
     106             :     const UChar *symbol = ucurr_getName(
     107             :             currency, locale, UCURR_SYMBOL_NAME, &unusedIsChoice,
     108           0 :             &len, &status);
     109           0 :     if (U_FAILURE(status)) {
     110           0 :         return;
     111             :     }
     112           0 :     fSymbol.setTo(symbol, len);
     113           0 :     fISO.setTo(currency, u_strlen(currency));
     114           0 :     fLong.remove();
     115           0 :     StringEnumeration* keywords = rules->getKeywords(status);
     116           0 :     if (U_FAILURE(status)) {
     117           0 :         return;
     118             :     }
     119             :     const UnicodeString* pluralCount;
     120           0 :     while ((pluralCount = keywords->snext(status)) != NULL) {
     121           0 :         CharString pCount;
     122           0 :         pCount.appendInvariantChars(*pluralCount, status);
     123             :         const UChar *pluralName = ucurr_getPluralName(
     124           0 :             currency, locale, &unusedIsChoice, pCount.data(),
     125           0 :             &len, &status);
     126           0 :         fLong.setVariant(pCount.data(), UnicodeString(pluralName, len), status);
     127             :     }
     128           0 :     delete keywords;
     129             : }
     130             : 
     131             : void
     132           0 : CurrencyAffixInfo::adjustPrecision(
     133             :         const UChar *currency, const UCurrencyUsage usage,
     134             :         FixedPrecision &precision, UErrorCode &status) {
     135           0 :     if (U_FAILURE(status)) {
     136           0 :         return;
     137             :     }
     138             : 
     139             :     int32_t digitCount = ucurr_getDefaultFractionDigitsForUsage(
     140           0 :             currency, usage, &status);
     141           0 :     precision.fMin.setFracDigitCount(digitCount);
     142           0 :     precision.fMax.setFracDigitCount(digitCount);
     143             :     double increment = ucurr_getRoundingIncrementForUsage(
     144           0 :             currency, usage, &status);
     145           0 :     if (increment == 0.0) {
     146           0 :         precision.fRoundingIncrement.clear();
     147             :     } else {
     148           0 :         precision.fRoundingIncrement.set(increment);
     149             :         // guard against round-off error
     150           0 :         precision.fRoundingIncrement.round(6);
     151             :     }
     152             : }
     153             : 
     154             : void
     155           0 : AffixPattern::addLiteral(
     156             :         const UChar *literal, int32_t start, int32_t len) {
     157           0 :     char32Count += u_countChar32(literal + start, len);
     158           0 :     literals.append(literal, start, len);
     159           0 :     int32_t tlen = tokens.length();
     160             :     // Takes 4 UChars to encode maximum literal length.
     161           0 :     UChar *tokenChars = tokens.getBuffer(tlen + 4);
     162             : 
     163             :     // find start of literal size. May be tlen if there is no literal.
     164             :     // While finding start of literal size, compute literal length
     165           0 :     int32_t literalLength = 0;
     166           0 :     int32_t tLiteralStart = tlen;
     167           0 :     while (tLiteralStart > 0 && UNPACK_TOKEN(tokenChars[tLiteralStart - 1]) == kLiteral) {
     168           0 :         tLiteralStart--;
     169           0 :         literalLength <<= 8;
     170           0 :         literalLength |= UNPACK_LENGTH(tokenChars[tLiteralStart]);
     171             :     }
     172             :     // Add number of chars we just added to literal
     173           0 :     literalLength += len;
     174             : 
     175             :     // Now encode the new length starting at tLiteralStart
     176           0 :     tlen = tLiteralStart;
     177           0 :     tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral, literalLength & 0xFF);
     178           0 :     literalLength >>= 8;
     179           0 :     while (literalLength) {
     180           0 :         tokenChars[tlen++] = PACK_TOKEN_AND_LENGTH(kLiteral | 0x80, literalLength & 0xFF);
     181           0 :         literalLength >>= 8;
     182             :     }
     183           0 :     tokens.releaseBuffer(tlen);
     184           0 : }
     185             : 
     186             : void
     187           0 : AffixPattern::add(ETokenType t) {
     188           0 :     add(t, 1);
     189           0 : }
     190             : 
     191             : void
     192           0 : AffixPattern::addCurrency(uint8_t count) {
     193           0 :     add(kCurrency, count);
     194           0 : }
     195             : 
     196             : void
     197           0 : AffixPattern::add(ETokenType t, uint8_t count) {
     198           0 :     U_ASSERT(t != kLiteral);
     199           0 :     char32Count += count;
     200           0 :     switch (t) {
     201             :     case kCurrency: 
     202           0 :         hasCurrencyToken = TRUE;
     203           0 :         break;
     204             :     case kPercent:
     205           0 :         hasPercentToken = TRUE;
     206           0 :         break;
     207             :     case kPerMill:
     208           0 :         hasPermillToken = TRUE;
     209           0 :         break;
     210             :     default:
     211             :         // Do nothing
     212           0 :         break;
     213             :     }
     214           0 :     tokens.append(PACK_TOKEN_AND_LENGTH(t, count));
     215           0 : }
     216             : 
     217             : AffixPattern &
     218           0 : AffixPattern::append(const AffixPattern &other) {
     219           0 :     AffixPatternIterator iter;
     220           0 :     other.iterator(iter);
     221           0 :     UnicodeString literal;
     222           0 :     while (iter.nextToken()) {
     223           0 :         switch (iter.getTokenType()) {
     224             :         case kLiteral:
     225           0 :             iter.getLiteral(literal);
     226           0 :             addLiteral(literal.getBuffer(), 0, literal.length());
     227           0 :             break;
     228             :         case kCurrency:
     229           0 :             addCurrency(iter.getTokenLength());
     230           0 :             break;
     231             :         default:
     232           0 :             add(iter.getTokenType());
     233           0 :             break;
     234             :         }
     235             :     }
     236           0 :     return *this;
     237             : }
     238             : 
     239             : void
     240           0 : AffixPattern::remove() {
     241           0 :     tokens.remove();
     242           0 :     literals.remove();
     243           0 :     hasCurrencyToken = FALSE;
     244           0 :     hasPercentToken = FALSE;
     245           0 :     hasPermillToken = FALSE;
     246           0 :     char32Count = 0;
     247           0 : }
     248             : 
     249             : // escapes literals for strings where special characters are NOT escaped
     250             : // except for apostrophe.
     251           0 : static void escapeApostropheInLiteral(
     252             :         const UnicodeString &literal, UnicodeStringAppender &appender) {
     253           0 :     int32_t len = literal.length();
     254           0 :     const UChar *buffer = literal.getBuffer();
     255           0 :     for (int32_t i = 0; i < len; ++i) {
     256           0 :         UChar ch = buffer[i];
     257           0 :         switch (ch) {
     258             :             case 0x27:
     259           0 :                 appender.append((UChar) 0x27);
     260           0 :                 appender.append((UChar) 0x27);
     261           0 :                 break;
     262             :             default:
     263           0 :                 appender.append(ch);
     264           0 :                 break;
     265             :         }
     266             :     }
     267           0 : }
     268             : 
     269             : 
     270             : // escapes literals for user strings where special characters in literals
     271             : // are escaped with apostrophe.
     272           0 : static void escapeLiteral(
     273             :         const UnicodeString &literal, UnicodeStringAppender &appender) {
     274           0 :     int32_t len = literal.length();
     275           0 :     const UChar *buffer = literal.getBuffer();
     276           0 :     for (int32_t i = 0; i < len; ++i) {
     277           0 :         UChar ch = buffer[i];
     278           0 :         switch (ch) {
     279             :             case 0x27:
     280           0 :                 appender.append((UChar) 0x27);
     281           0 :                 appender.append((UChar) 0x27);
     282           0 :                 break;
     283             :             case 0x25:
     284           0 :                 appender.append((UChar) 0x27);
     285           0 :                 appender.append((UChar) 0x25);
     286           0 :                 appender.append((UChar) 0x27);
     287           0 :                 break;
     288             :             case 0x2030:
     289           0 :                 appender.append((UChar) 0x27);
     290           0 :                 appender.append((UChar) 0x2030);
     291           0 :                 appender.append((UChar) 0x27);
     292           0 :                 break;
     293             :             case 0xA4:
     294           0 :                 appender.append((UChar) 0x27);
     295           0 :                 appender.append((UChar) 0xA4);
     296           0 :                 appender.append((UChar) 0x27);
     297           0 :                 break;
     298             :             case 0x2D:
     299           0 :                 appender.append((UChar) 0x27);
     300           0 :                 appender.append((UChar) 0x2D);
     301           0 :                 appender.append((UChar) 0x27);
     302           0 :                 break;
     303             :             case 0x2B:
     304           0 :                 appender.append((UChar) 0x27);
     305           0 :                 appender.append((UChar) 0x2B);
     306           0 :                 appender.append((UChar) 0x27);
     307           0 :                 break;
     308             :             default:
     309           0 :                 appender.append(ch);
     310           0 :                 break;
     311             :         }
     312             :     }
     313           0 : }
     314             : 
     315             : UnicodeString &
     316           0 : AffixPattern::toString(UnicodeString &appendTo) const {
     317           0 :     AffixPatternIterator iter;
     318           0 :     iterator(iter);
     319           0 :     UnicodeStringAppender appender(appendTo);
     320           0 :     UnicodeString literal;
     321           0 :     while (iter.nextToken()) {
     322           0 :         switch (iter.getTokenType()) {
     323             :         case kLiteral:
     324           0 :             escapeApostropheInLiteral(iter.getLiteral(literal), appender);
     325           0 :             break;
     326             :         case kPercent:
     327           0 :             appender.append((UChar) 0x27);
     328           0 :             appender.append((UChar) 0x25);
     329           0 :             break;
     330             :         case kPerMill:
     331           0 :             appender.append((UChar) 0x27);
     332           0 :             appender.append((UChar) 0x2030);
     333           0 :             break;
     334             :         case kCurrency:
     335             :             {
     336           0 :                 appender.append((UChar) 0x27);
     337           0 :                 int32_t cl = iter.getTokenLength();
     338           0 :                 for (int32_t i = 0; i < cl; ++i) {
     339           0 :                     appender.append((UChar) 0xA4);
     340             :                 }
     341             :             }
     342           0 :             break;
     343             :         case kNegative:
     344           0 :             appender.append((UChar) 0x27);
     345           0 :             appender.append((UChar) 0x2D);
     346           0 :             break;
     347             :         case kPositive:
     348           0 :             appender.append((UChar) 0x27);
     349           0 :             appender.append((UChar) 0x2B);
     350           0 :             break;
     351             :         default:
     352           0 :             U_ASSERT(FALSE);
     353             :             break;
     354             :         }
     355             :     }
     356           0 :     return appendTo;
     357             : }
     358             : 
     359             : UnicodeString &
     360           0 : AffixPattern::toUserString(UnicodeString &appendTo) const {
     361           0 :     AffixPatternIterator iter;
     362           0 :     iterator(iter);
     363           0 :     UnicodeStringAppender appender(appendTo);
     364           0 :     UnicodeString literal;
     365           0 :     while (iter.nextToken()) {
     366           0 :         switch (iter.getTokenType()) {
     367             :         case kLiteral:
     368           0 :             escapeLiteral(iter.getLiteral(literal), appender);
     369           0 :             break;
     370             :         case kPercent:
     371           0 :             appender.append((UChar) 0x25);
     372           0 :             break;
     373             :         case kPerMill:
     374           0 :             appender.append((UChar) 0x2030);
     375           0 :             break;
     376             :         case kCurrency:
     377             :             {
     378           0 :                 int32_t cl = iter.getTokenLength();
     379           0 :                 for (int32_t i = 0; i < cl; ++i) {
     380           0 :                     appender.append((UChar) 0xA4);
     381             :                 }
     382             :             }
     383           0 :             break;
     384             :         case kNegative:
     385           0 :             appender.append((UChar) 0x2D);
     386           0 :             break;
     387             :         case kPositive:
     388           0 :             appender.append((UChar) 0x2B);
     389           0 :             break;
     390             :         default:
     391           0 :             U_ASSERT(FALSE);
     392             :             break;
     393             :         }
     394             :     }
     395           0 :     return appendTo;
     396             : }
     397             : 
     398             : class AffixPatternAppender : public UMemory {
     399             : public:
     400           0 :     AffixPatternAppender(AffixPattern &dest) : fDest(&dest), fIdx(0) { }
     401             : 
     402           0 :     inline void append(UChar x) {
     403           0 :         if (fIdx == UPRV_LENGTHOF(fBuffer)) {
     404           0 :             fDest->addLiteral(fBuffer, 0, fIdx);
     405           0 :             fIdx = 0;
     406             :         }
     407           0 :         fBuffer[fIdx++] = x;
     408           0 :     }
     409             : 
     410             :     inline void append(UChar32 x) {
     411             :         if (fIdx >= UPRV_LENGTHOF(fBuffer) - 1) {
     412             :             fDest->addLiteral(fBuffer, 0, fIdx);
     413             :             fIdx = 0;
     414             :         }
     415             :         U16_APPEND_UNSAFE(fBuffer, fIdx, x);
     416             :     }
     417             : 
     418           0 :     inline void flush() {
     419           0 :         if (fIdx) {
     420           0 :             fDest->addLiteral(fBuffer, 0, fIdx);
     421             :         }
     422           0 :         fIdx = 0;
     423           0 :     }
     424             : 
     425             :     /**
     426             :      * flush the buffer when we go out of scope.
     427             :      */
     428           0 :     ~AffixPatternAppender() {
     429           0 :         flush();
     430           0 :     }
     431             : private:
     432             :     AffixPattern *fDest;
     433             :     int32_t fIdx;
     434             :     UChar fBuffer[32];
     435             :     AffixPatternAppender(const AffixPatternAppender &other);
     436             :     AffixPatternAppender &operator=(const AffixPatternAppender &other);
     437             : };
     438             : 
     439             : 
     440             : AffixPattern &
     441           0 : AffixPattern::parseUserAffixString(
     442             :         const UnicodeString &affixStr,
     443             :         AffixPattern &appendTo, 
     444             :         UErrorCode &status) {
     445           0 :     if (U_FAILURE(status)) {
     446           0 :         return appendTo;
     447             :     }
     448           0 :     int32_t len = affixStr.length();
     449           0 :     const UChar *buffer = affixStr.getBuffer();
     450             :     // 0 = not quoted; 1 = quoted.
     451           0 :     int32_t state = 0;
     452           0 :     AffixPatternAppender appender(appendTo);
     453           0 :     for (int32_t i = 0; i < len; ) {
     454             :         UChar token;
     455           0 :         int32_t tokenSize = nextUserToken(buffer, i, len, &token);
     456           0 :         i += tokenSize;
     457           0 :         if (token == 0x27 && tokenSize == 1) { // quote
     458           0 :             state = 1 - state;
     459           0 :             continue;
     460             :         }
     461           0 :         if (state == 0) {
     462           0 :             switch (token) {
     463             :             case 0x25:
     464           0 :                 appender.flush();
     465           0 :                 appendTo.add(kPercent, 1);
     466           0 :                 break;
     467             :             case 0x27:  // double quote
     468           0 :                 appender.append((UChar) 0x27);
     469           0 :                 break;
     470             :             case 0x2030:
     471           0 :                 appender.flush();
     472           0 :                 appendTo.add(kPerMill, 1);
     473           0 :                 break;
     474             :             case 0x2D:
     475           0 :                 appender.flush();
     476           0 :                 appendTo.add(kNegative, 1);
     477           0 :                 break;
     478             :             case 0x2B:
     479           0 :                 appender.flush();
     480           0 :                 appendTo.add(kPositive, 1);
     481           0 :                 break;
     482             :             case 0xA4:
     483           0 :                 appender.flush();
     484           0 :                 appendTo.add(kCurrency, tokenSize);
     485           0 :                 break;
     486             :             default:
     487           0 :                 appender.append(token);
     488           0 :                 break;
     489             :             }
     490             :         } else {
     491           0 :             switch (token) {
     492             :             case 0x27:  // double quote
     493           0 :                 appender.append((UChar) 0x27);
     494           0 :                 break;
     495             :             case 0xA4: // included b/c tokenSize can be > 1
     496           0 :                 for (int32_t j = 0; j < tokenSize; ++j) {
     497           0 :                     appender.append((UChar) 0xA4);
     498             :                 }
     499           0 :                 break;
     500             :             default:
     501           0 :                 appender.append(token);
     502           0 :                 break;
     503             :             }
     504             :         }
     505             :     }
     506           0 :     return appendTo;
     507             : }
     508             : 
     509             : AffixPattern &
     510           0 : AffixPattern::parseAffixString(
     511             :         const UnicodeString &affixStr,
     512             :         AffixPattern &appendTo, 
     513             :         UErrorCode &status) {
     514           0 :     if (U_FAILURE(status)) {
     515           0 :         return appendTo;
     516             :     }
     517           0 :     int32_t len = affixStr.length();
     518           0 :     const UChar *buffer = affixStr.getBuffer();
     519           0 :     for (int32_t i = 0; i < len; ) {
     520             :         UChar token;
     521           0 :         int32_t tokenSize = nextToken(buffer, i, len, &token);
     522           0 :         if (tokenSize == 1) {
     523           0 :             int32_t literalStart = i;
     524           0 :             ++i;
     525           0 :             while (i < len && (tokenSize = nextToken(buffer, i, len, &token)) == 1) {
     526           0 :                 ++i;
     527             :             }
     528           0 :             appendTo.addLiteral(buffer, literalStart, i - literalStart);
     529             : 
     530             :             // If we reached end of string, we are done
     531           0 :             if (i == len) {
     532           0 :                 return appendTo;
     533             :             }
     534             :         }
     535           0 :         i += tokenSize;
     536           0 :         switch (token) {
     537             :         case 0x25:
     538           0 :             appendTo.add(kPercent, 1);
     539           0 :             break;
     540             :         case 0x2030:
     541           0 :             appendTo.add(kPerMill, 1);
     542           0 :             break;
     543             :         case 0x2D:
     544           0 :             appendTo.add(kNegative, 1);
     545           0 :             break;
     546             :         case 0x2B:
     547           0 :             appendTo.add(kPositive, 1);
     548           0 :             break;
     549             :         case 0xA4:
     550             :             {
     551           0 :                 if (tokenSize - 1 > 3) {
     552           0 :                     status = U_PARSE_ERROR;
     553           0 :                     return appendTo;
     554             :                 }
     555           0 :                 appendTo.add(kCurrency, tokenSize - 1);
     556             :             }
     557           0 :             break;
     558             :         default:
     559           0 :             appendTo.addLiteral(&token, 0, 1);
     560           0 :             break;
     561             :         }
     562             :     }
     563           0 :     return appendTo;
     564             : }
     565             : 
     566             : AffixPatternIterator &
     567           0 : AffixPattern::iterator(AffixPatternIterator &result) const {
     568           0 :     result.nextLiteralIndex = 0;
     569           0 :     result.lastLiteralLength = 0;
     570           0 :     result.nextTokenIndex = 0;
     571           0 :     result.tokens = &tokens;
     572           0 :     result.literals = &literals;
     573           0 :     return result;
     574             : }
     575             : 
     576             : UBool
     577           0 : AffixPatternIterator::nextToken() {
     578           0 :     int32_t tlen = tokens->length();
     579           0 :     if (nextTokenIndex == tlen) {
     580           0 :         return FALSE;
     581             :     }
     582           0 :     ++nextTokenIndex;
     583           0 :     const UChar *tokenBuffer = tokens->getBuffer();
     584           0 :     if (UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]) ==
     585             :             AffixPattern::kLiteral) {
     586           0 :         while (nextTokenIndex < tlen &&
     587           0 :                 UNPACK_LONG(tokenBuffer[nextTokenIndex])) {
     588           0 :             ++nextTokenIndex;
     589             :         }
     590           0 :         lastLiteralLength = 0;
     591           0 :         int32_t i = nextTokenIndex - 1;
     592           0 :         for (; UNPACK_LONG(tokenBuffer[i]); --i) {
     593           0 :             lastLiteralLength <<= 8;
     594           0 :             lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]);
     595             :         }
     596           0 :         lastLiteralLength <<= 8;
     597           0 :         lastLiteralLength |= UNPACK_LENGTH(tokenBuffer[i]);
     598           0 :         nextLiteralIndex += lastLiteralLength;
     599             :     }
     600           0 :     return TRUE;
     601             : }
     602             : 
     603             : AffixPattern::ETokenType
     604           0 : AffixPatternIterator::getTokenType() const {
     605           0 :     return UNPACK_TOKEN(tokens->charAt(nextTokenIndex - 1));
     606             : }
     607             : 
     608             : UnicodeString &
     609           0 : AffixPatternIterator::getLiteral(UnicodeString &result) const {
     610           0 :     const UChar *buffer = literals->getBuffer();
     611           0 :     result.setTo(buffer + (nextLiteralIndex - lastLiteralLength), lastLiteralLength);
     612           0 :     return result;
     613             : }
     614             : 
     615             : int32_t
     616           0 : AffixPatternIterator::getTokenLength() const {
     617           0 :     const UChar *tokenBuffer = tokens->getBuffer();
     618           0 :     AffixPattern::ETokenType type = UNPACK_TOKEN(tokenBuffer[nextTokenIndex - 1]);
     619           0 :     return type == AffixPattern::kLiteral ? lastLiteralLength : UNPACK_LENGTH(tokenBuffer[nextTokenIndex - 1]);
     620             : }
     621             : 
     622           0 : AffixPatternParser::AffixPatternParser()
     623           0 :         : fPercent(gPercent), fPermill(gPerMill), fNegative(gNegative), fPositive(gPositive) {
     624           0 : }
     625             : 
     626           0 : AffixPatternParser::AffixPatternParser(
     627           0 :         const DecimalFormatSymbols &symbols) {
     628           0 :     setDecimalFormatSymbols(symbols);
     629           0 : }
     630             : 
     631             : void
     632           0 : AffixPatternParser::setDecimalFormatSymbols(
     633             :         const DecimalFormatSymbols &symbols) {
     634           0 :     fPercent = symbols.getConstSymbol(DecimalFormatSymbols::kPercentSymbol);
     635           0 :     fPermill = symbols.getConstSymbol(DecimalFormatSymbols::kPerMillSymbol);
     636           0 :     fNegative = symbols.getConstSymbol(DecimalFormatSymbols::kMinusSignSymbol);
     637           0 :     fPositive = symbols.getConstSymbol(DecimalFormatSymbols::kPlusSignSymbol);
     638           0 : }
     639             : 
     640             : PluralAffix &
     641           0 : AffixPatternParser::parse(
     642             :         const AffixPattern &affixPattern,
     643             :         const CurrencyAffixInfo &currencyAffixInfo,
     644             :         PluralAffix &appendTo, 
     645             :         UErrorCode &status) const {
     646           0 :     if (U_FAILURE(status)) {
     647           0 :         return appendTo;
     648             :     }
     649           0 :     AffixPatternIterator iter;
     650           0 :     affixPattern.iterator(iter);
     651           0 :     UnicodeString literal;
     652           0 :     while (iter.nextToken()) {
     653           0 :         switch (iter.getTokenType()) {
     654             :         case AffixPattern::kPercent:
     655           0 :             appendTo.append(fPercent, UNUM_PERCENT_FIELD);
     656           0 :             break;
     657             :         case AffixPattern::kPerMill:
     658           0 :             appendTo.append(fPermill, UNUM_PERMILL_FIELD);
     659           0 :             break;
     660             :         case AffixPattern::kNegative:
     661           0 :             appendTo.append(fNegative, UNUM_SIGN_FIELD);
     662           0 :             break;
     663             :         case AffixPattern::kPositive:
     664           0 :             appendTo.append(fPositive, UNUM_SIGN_FIELD);
     665           0 :             break;
     666             :         case AffixPattern::kCurrency:
     667           0 :             switch (iter.getTokenLength()) {
     668             :                 case 1:
     669           0 :                     appendTo.append(
     670           0 :                             currencyAffixInfo.getSymbol(), UNUM_CURRENCY_FIELD);
     671           0 :                     break;
     672             :                 case 2:
     673           0 :                     appendTo.append(
     674           0 :                             currencyAffixInfo.getISO(), UNUM_CURRENCY_FIELD);
     675           0 :                     break;
     676             :                 case 3:
     677           0 :                     appendTo.append(
     678           0 :                             currencyAffixInfo.getLong(), UNUM_CURRENCY_FIELD, status);
     679           0 :                     break;
     680             :                 default:
     681           0 :                     U_ASSERT(FALSE);
     682             :                     break;
     683             :             }
     684           0 :             break;
     685             :         case AffixPattern::kLiteral:
     686           0 :             appendTo.append(iter.getLiteral(literal));
     687           0 :             break;
     688             :         default:
     689           0 :             U_ASSERT(FALSE);
     690             :             break;
     691             :         }
     692             :     }
     693           0 :     return appendTo;
     694             : }
     695             : 
     696             : 
     697             : U_NAMESPACE_END
     698             : #endif /* #if !UCONFIG_NO_FORMATTING */

Generated by: LCOV version 1.13