LCOV - code coverage report
Current view: top level - intl/icu/source/i18n - currpinf.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 183 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 22 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-2014, International Business Machines Corporation and
       6             :  * others. All Rights Reserved.
       7             :  *******************************************************************************
       8             :  */
       9             : 
      10             : #include "unicode/currpinf.h"
      11             : 
      12             : #if !UCONFIG_NO_FORMATTING
      13             : 
      14             : //#define CURRENCY_PLURAL_INFO_DEBUG 1
      15             : 
      16             : #ifdef CURRENCY_PLURAL_INFO_DEBUG
      17             : #include <iostream>
      18             : #endif
      19             : 
      20             : 
      21             : #include "unicode/locid.h"
      22             : #include "unicode/plurrule.h"
      23             : #include "unicode/strenum.h"
      24             : #include "unicode/ures.h"
      25             : #include "unicode/numsys.h"
      26             : #include "cstring.h"
      27             : #include "hash.h"
      28             : #include "uresimp.h"
      29             : #include "ureslocs.h"
      30             : 
      31             : U_NAMESPACE_BEGIN
      32             : 
      33             : 
      34             : static const UChar gNumberPatternSeparator = 0x3B; // ;
      35             : 
      36             : U_CDECL_BEGIN
      37             : 
      38             : /**
      39             :  * @internal ICU 4.2
      40             :  */
      41             : static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2);
      42             : 
      43             : UBool
      44           0 : U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) {
      45           0 :     const UnicodeString* affix_1 = (UnicodeString*)val1.pointer;
      46           0 :     const UnicodeString* affix_2 = (UnicodeString*)val2.pointer;
      47           0 :     return  *affix_1 == *affix_2;
      48             : }
      49             : 
      50             : U_CDECL_END
      51             : 
      52             : 
      53           0 : UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo)
      54             : 
      55             : static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0};
      56             : static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0};
      57             : static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0};
      58             : static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0};
      59             : static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0};
      60             : 
      61             : static const char gNumberElementsTag[]="NumberElements";
      62             : static const char gLatnTag[]="latn";
      63             : static const char gPatternsTag[]="patterns";
      64             : static const char gDecimalFormatTag[]="decimalFormat";
      65             : static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns";
      66             : 
      67           0 : CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status)
      68             : :   fPluralCountToCurrencyUnitPattern(NULL),
      69             :     fPluralRules(NULL),
      70           0 :     fLocale(NULL) {
      71           0 :     initialize(Locale::getDefault(), status);
      72           0 : }
      73             : 
      74           0 : CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status)
      75             : :   fPluralCountToCurrencyUnitPattern(NULL),
      76             :     fPluralRules(NULL),
      77           0 :     fLocale(NULL) {
      78           0 :     initialize(locale, status);
      79           0 : }
      80             : 
      81           0 : CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) 
      82             : :   UObject(info),
      83             :     fPluralCountToCurrencyUnitPattern(NULL),
      84             :     fPluralRules(NULL),
      85           0 :     fLocale(NULL) {
      86           0 :     *this = info;
      87           0 : }
      88             : 
      89             : 
      90             : CurrencyPluralInfo&
      91           0 : CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) {
      92           0 :     if (this == &info) {
      93           0 :         return *this;
      94             :     }
      95             : 
      96           0 :     deleteHash(fPluralCountToCurrencyUnitPattern);
      97           0 :     UErrorCode status = U_ZERO_ERROR;
      98           0 :     fPluralCountToCurrencyUnitPattern = initHash(status);
      99           0 :     copyHash(info.fPluralCountToCurrencyUnitPattern, 
     100           0 :              fPluralCountToCurrencyUnitPattern, status);
     101           0 :     if ( U_FAILURE(status) ) {
     102           0 :         return *this;
     103             :     }
     104             : 
     105           0 :     delete fPluralRules;
     106           0 :     delete fLocale;
     107           0 :     if (info.fPluralRules) {
     108           0 :         fPluralRules = info.fPluralRules->clone();
     109             :     } else {
     110           0 :         fPluralRules = NULL;
     111             :     }
     112           0 :     if (info.fLocale) {
     113           0 :         fLocale = info.fLocale->clone();
     114             :     } else {
     115           0 :         fLocale = NULL;
     116             :     }
     117           0 :     return *this;
     118             : }
     119             : 
     120             : 
     121           0 : CurrencyPluralInfo::~CurrencyPluralInfo() {
     122           0 :     deleteHash(fPluralCountToCurrencyUnitPattern);
     123           0 :     fPluralCountToCurrencyUnitPattern = NULL;
     124           0 :     delete fPluralRules;
     125           0 :     delete fLocale;
     126           0 :     fPluralRules = NULL;
     127           0 :     fLocale = NULL;
     128           0 : }
     129             : 
     130             : UBool
     131           0 : CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const {
     132             : #ifdef CURRENCY_PLURAL_INFO_DEBUG
     133             :     if (*fPluralRules == *info.fPluralRules) {
     134             :         std::cout << "same plural rules\n";
     135             :     }
     136             :     if (*fLocale == *info.fLocale) {
     137             :         std::cout << "same locale\n";
     138             :     }
     139             :     if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) {
     140             :         std::cout << "same pattern\n";
     141             :     }
     142             : #endif
     143           0 :     return *fPluralRules == *info.fPluralRules &&
     144           0 :            *fLocale == *info.fLocale &&
     145           0 :            fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern);
     146             : }
     147             : 
     148             : 
     149             : CurrencyPluralInfo*
     150           0 : CurrencyPluralInfo::clone() const {
     151           0 :     return new CurrencyPluralInfo(*this);
     152             : }
     153             : 
     154             : const PluralRules* 
     155           0 : CurrencyPluralInfo::getPluralRules() const {
     156           0 :     return fPluralRules;
     157             : }
     158             : 
     159             : UnicodeString&
     160           0 : CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString&  pluralCount,
     161             :                                              UnicodeString& result) const {
     162             :     const UnicodeString* currencyPluralPattern = 
     163           0 :         (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount);
     164           0 :     if (currencyPluralPattern == NULL) {
     165             :         // fall back to "other"
     166           0 :         if (pluralCount.compare(gPluralCountOther, 5)) {
     167             :             currencyPluralPattern = 
     168           0 :                 (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(UnicodeString(TRUE, gPluralCountOther, 5));
     169             :         }
     170           0 :         if (currencyPluralPattern == NULL) {
     171             :             // no currencyUnitPatterns defined, 
     172             :             // fallback to predefined defult.
     173             :             // This should never happen when ICU resource files are
     174             :             // available, since currencyUnitPattern of "other" is always
     175             :             // defined in root.
     176           0 :             result = UnicodeString(gDefaultCurrencyPluralPattern);
     177           0 :             return result;
     178             :         }
     179             :     }
     180           0 :     result = *currencyPluralPattern;
     181           0 :     return result;
     182             : }
     183             : 
     184             : const Locale&
     185           0 : CurrencyPluralInfo::getLocale() const {
     186           0 :     return *fLocale;
     187             : }
     188             : 
     189             : void
     190           0 : CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription,
     191             :                                    UErrorCode& status) {
     192           0 :     if (U_SUCCESS(status)) {
     193           0 :         if (fPluralRules) {
     194           0 :             delete fPluralRules;
     195             :         }
     196           0 :         fPluralRules = PluralRules::createRules(ruleDescription, status);
     197             :     }
     198           0 : }
     199             : 
     200             : 
     201             : void
     202           0 : CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount,
     203             :                                              const UnicodeString& pattern,
     204             :                                              UErrorCode& status) {
     205           0 :     if (U_SUCCESS(status)) {
     206           0 :         fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status);
     207             :     }
     208           0 : }
     209             : 
     210             : 
     211             : void
     212           0 : CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) {
     213           0 :     initialize(loc, status);
     214           0 : }
     215             : 
     216             : 
     217             : void 
     218           0 : CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) {
     219           0 :     if (U_FAILURE(status)) {
     220           0 :         return;
     221             :     }
     222           0 :     delete fLocale;
     223           0 :     fLocale = loc.clone();
     224           0 :     if (fPluralRules) {
     225           0 :         delete fPluralRules;
     226             :     }
     227           0 :     fPluralRules = PluralRules::forLocale(loc, status);
     228           0 :     setupCurrencyPluralPattern(loc, status);
     229             : }
     230             : 
     231             :    
     232             : void
     233           0 : CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) {
     234           0 :     if (U_FAILURE(status)) {
     235           0 :         return;
     236             :     }
     237             : 
     238           0 :     if (fPluralCountToCurrencyUnitPattern) {
     239           0 :         deleteHash(fPluralCountToCurrencyUnitPattern);
     240             :     }
     241           0 :     fPluralCountToCurrencyUnitPattern = initHash(status);
     242           0 :     if (U_FAILURE(status)) {
     243           0 :         return;
     244             :     }
     245             : 
     246           0 :     NumberingSystem *ns = NumberingSystem::createInstance(loc,status);
     247           0 :     UErrorCode ec = U_ZERO_ERROR;
     248           0 :     UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec);
     249           0 :     UResourceBundle *numElements = ures_getByKeyWithFallback(rb, gNumberElementsTag, NULL, &ec);
     250           0 :     rb = ures_getByKeyWithFallback(numElements, ns->getName(), rb, &ec);
     251           0 :     rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec);
     252             :     int32_t ptnLen;
     253           0 :     const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec);
     254             :     // Fall back to "latn" if num sys specific pattern isn't there.
     255           0 :     if ( ec == U_MISSING_RESOURCE_ERROR && uprv_strcmp(ns->getName(),gLatnTag)) {
     256           0 :         ec = U_ZERO_ERROR;
     257           0 :         rb = ures_getByKeyWithFallback(numElements, gLatnTag, rb, &ec);
     258           0 :         rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec);
     259           0 :         numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec);
     260             :     }
     261           0 :     int32_t numberStylePatternLen = ptnLen;
     262           0 :     const UChar* negNumberStylePattern = NULL;
     263           0 :     int32_t negNumberStylePatternLen = 0;
     264             :     // TODO: Java
     265             :     // parse to check whether there is ";" separator in the numberStylePattern
     266           0 :     UBool hasSeparator = false;
     267           0 :     if (U_SUCCESS(ec)) {
     268           0 :         for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) {
     269           0 :             if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) {
     270           0 :                 hasSeparator = true;
     271             :                 // split the number style pattern into positive and negative
     272           0 :                 negNumberStylePattern = numberStylePattern + styleCharIndex + 1;
     273           0 :                 negNumberStylePatternLen = ptnLen - styleCharIndex - 1;
     274           0 :                 numberStylePatternLen = styleCharIndex;
     275             :             }
     276             :         }
     277             :     }
     278             : 
     279           0 :     ures_close(numElements);
     280           0 :     ures_close(rb);
     281           0 :     delete ns;
     282             : 
     283           0 :     if (U_FAILURE(ec)) {
     284           0 :         return;
     285             :     }
     286             : 
     287           0 :     UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec);
     288           0 :     UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec);
     289             :     
     290             : #ifdef CURRENCY_PLURAL_INFO_DEBUG
     291             :     std::cout << "in set up\n";
     292             : #endif
     293           0 :     StringEnumeration* keywords = fPluralRules->getKeywords(ec);
     294           0 :     if (U_SUCCESS(ec)) {
     295             :         const char* pluralCount;
     296           0 :         while ((pluralCount = keywords->next(NULL, ec)) != NULL) {
     297           0 :             if ( U_SUCCESS(ec) ) {
     298             :                 int32_t ptnLen;
     299           0 :                 UErrorCode err = U_ZERO_ERROR;
     300             :                 const UChar* patternChars = ures_getStringByKeyWithFallback(
     301           0 :                     currencyRes, pluralCount, &ptnLen, &err);
     302           0 :                 if (U_SUCCESS(err) && ptnLen > 0) {
     303           0 :                     UnicodeString* pattern = new UnicodeString(patternChars, ptnLen);
     304             : #ifdef CURRENCY_PLURAL_INFO_DEBUG
     305             :                     char result_1[1000];
     306             :                     pattern->extract(0, pattern->length(), result_1, "UTF-8");
     307             :                     std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
     308             : #endif
     309           0 :                     pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), 
     310           0 :                       UnicodeString(numberStylePattern, numberStylePatternLen));
     311           0 :                     pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3));
     312             : 
     313           0 :                     if (hasSeparator) {
     314           0 :                         UnicodeString negPattern(patternChars, ptnLen);
     315           0 :                         negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), 
     316           0 :                           UnicodeString(negNumberStylePattern, negNumberStylePatternLen));
     317           0 :                         negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3));
     318           0 :                         pattern->append(gNumberPatternSeparator);
     319           0 :                         pattern->append(negPattern);
     320             :                     }
     321             : #ifdef CURRENCY_PLURAL_INFO_DEBUG
     322             :                     pattern->extract(0, pattern->length(), result_1, "UTF-8");
     323             :                     std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n";
     324             : #endif
     325             : 
     326           0 :                     fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status);
     327             :                 }
     328             :             }
     329             :         }
     330             :     }
     331           0 :     delete keywords;
     332           0 :     ures_close(currencyRes);
     333           0 :     ures_close(currRb);
     334             : }
     335             : 
     336             : 
     337             : 
     338             : void
     339           0 : CurrencyPluralInfo::deleteHash(Hashtable* hTable) 
     340             : {
     341           0 :     if ( hTable == NULL ) {
     342           0 :         return;
     343             :     }
     344           0 :     int32_t pos = UHASH_FIRST;
     345           0 :     const UHashElement* element = NULL;
     346           0 :     while ( (element = hTable->nextElement(pos)) != NULL ) {
     347           0 :         const UHashTok valueTok = element->value;
     348           0 :         const UnicodeString* value = (UnicodeString*)valueTok.pointer;
     349           0 :         delete value;
     350             :     }
     351           0 :     delete hTable;
     352           0 :     hTable = NULL;
     353             : }
     354             : 
     355             : 
     356             : Hashtable*
     357           0 : CurrencyPluralInfo::initHash(UErrorCode& status) {
     358           0 :     if ( U_FAILURE(status) ) {
     359           0 :         return NULL;
     360             :     }
     361             :     Hashtable* hTable;
     362           0 :     if ( (hTable = new Hashtable(TRUE, status)) == NULL ) {
     363           0 :         status = U_MEMORY_ALLOCATION_ERROR;
     364           0 :         return NULL;
     365             :     }
     366           0 :     if ( U_FAILURE(status) ) {
     367           0 :         delete hTable; 
     368           0 :         return NULL;
     369             :     }
     370           0 :     hTable->setValueComparator(ValueComparator);
     371           0 :     return hTable;
     372             : }
     373             : 
     374             : 
     375             : void
     376           0 : CurrencyPluralInfo::copyHash(const Hashtable* source,
     377             :                            Hashtable* target,
     378             :                            UErrorCode& status) {
     379           0 :     if ( U_FAILURE(status) ) {
     380           0 :         return;
     381             :     }
     382           0 :     int32_t pos = UHASH_FIRST;
     383           0 :     const UHashElement* element = NULL;
     384           0 :     if ( source ) {
     385           0 :         while ( (element = source->nextElement(pos)) != NULL ) {
     386           0 :             const UHashTok keyTok = element->key;
     387           0 :             const UnicodeString* key = (UnicodeString*)keyTok.pointer;
     388           0 :             const UHashTok valueTok = element->value;
     389           0 :             const UnicodeString* value = (UnicodeString*)valueTok.pointer;
     390           0 :             UnicodeString* copy = new UnicodeString(*value);
     391           0 :             target->put(UnicodeString(*key), copy, status);
     392           0 :             if ( U_FAILURE(status) ) {
     393           0 :                 return;
     394             :             }
     395             :         }
     396             :     }
     397             : }
     398             : 
     399             : 
     400             : U_NAMESPACE_END
     401             : 
     402             : #endif

Generated by: LCOV version 1.13