intl/icu/source/i18n/currpinf.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

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

mercurial