Index: icu46/source/i18n/currpinf.cpp |
=================================================================== |
--- icu46/source/i18n/currpinf.cpp (revision 0) |
+++ icu46/source/i18n/currpinf.cpp (revision 0) |
@@ -0,0 +1,384 @@ |
+/* |
+ ******************************************************************************* |
+ * Copyright (C) 2009-2010, International Business Machines Corporation and |
+ * others. All Rights Reserved. |
+ ******************************************************************************* |
+ */ |
+ |
+#include "unicode/currpinf.h" |
+ |
+#if !UCONFIG_NO_FORMATTING |
+ |
+//#define CURRENCY_PLURAL_INFO_DEBUG 1 |
+ |
+#ifdef CURRENCY_PLURAL_INFO_DEBUG |
+#include <iostream> |
+#endif |
+ |
+ |
+#include "unicode/locid.h" |
+#include "unicode/plurrule.h" |
+#include "unicode/ures.h" |
+#include "cstring.h" |
+#include "hash.h" |
+#include "uresimp.h" |
+#include "ureslocs.h" |
+ |
+U_NAMESPACE_BEGIN |
+ |
+ |
+static const UChar gNumberPatternSeparator = 0x3B; // ; |
+ |
+U_CDECL_BEGIN |
+ |
+/** |
+ * @internal ICU 4.2 |
+ */ |
+static UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2); |
+ |
+UBool |
+U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) { |
+ const UnicodeString* affix_1 = (UnicodeString*)val1.pointer; |
+ const UnicodeString* affix_2 = (UnicodeString*)val2.pointer; |
+ return *affix_1 == *affix_2; |
+} |
+ |
+U_CDECL_END |
+ |
+ |
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo) |
+ |
+static const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0}; |
+static const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0}; |
+static const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0}; |
+static const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0}; |
+static const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0}; |
+ |
+static const char gNumberElementsTag[]="NumberElements"; |
+static const char gLatnTag[]="latn"; |
+static const char gPatternsTag[]="patterns"; |
+static const char gDecimalFormatTag[]="decimalFormat"; |
+static const char gCurrUnitPtnTag[]="CurrencyUnitPatterns"; |
+ |
+CurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status) |
+: fPluralCountToCurrencyUnitPattern(NULL), |
+ fPluralRules(NULL), |
+ fLocale(NULL) { |
+ initialize(Locale::getDefault(), status); |
+} |
+ |
+CurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status) |
+: fPluralCountToCurrencyUnitPattern(NULL), |
+ fPluralRules(NULL), |
+ fLocale(NULL) { |
+ initialize(locale, status); |
+} |
+ |
+CurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) |
+: UObject(info), |
+ fPluralCountToCurrencyUnitPattern(NULL), |
+ fPluralRules(NULL), |
+ fLocale(NULL) { |
+ *this = info; |
+} |
+ |
+ |
+CurrencyPluralInfo& |
+CurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) { |
+ if (this == &info) { |
+ return *this; |
+ } |
+ |
+ deleteHash(fPluralCountToCurrencyUnitPattern); |
+ UErrorCode status = U_ZERO_ERROR; |
+ fPluralCountToCurrencyUnitPattern = initHash(status); |
+ copyHash(info.fPluralCountToCurrencyUnitPattern, |
+ fPluralCountToCurrencyUnitPattern, status); |
+ if ( U_FAILURE(status) ) { |
+ return *this; |
+ } |
+ |
+ delete fPluralRules; |
+ delete fLocale; |
+ if (info.fPluralRules) { |
+ fPluralRules = info.fPluralRules->clone(); |
+ } else { |
+ fPluralRules = NULL; |
+ } |
+ if (info.fLocale) { |
+ fLocale = info.fLocale->clone(); |
+ } else { |
+ fLocale = NULL; |
+ } |
+ return *this; |
+} |
+ |
+ |
+CurrencyPluralInfo::~CurrencyPluralInfo() { |
+ deleteHash(fPluralCountToCurrencyUnitPattern); |
+ fPluralCountToCurrencyUnitPattern = NULL; |
+ delete fPluralRules; |
+ delete fLocale; |
+ fPluralRules = NULL; |
+ fLocale = NULL; |
+} |
+ |
+UBool |
+CurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const { |
+#ifdef CURRENCY_PLURAL_INFO_DEBUG |
+ if (*fPluralRules == *info.fPluralRules) { |
+ std::cout << "same plural rules\n"; |
+ } |
+ if (*fLocale == *info.fLocale) { |
+ std::cout << "same locale\n"; |
+ } |
+ if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) { |
+ std::cout << "same pattern\n"; |
+ } |
+#endif |
+ return *fPluralRules == *info.fPluralRules && |
+ *fLocale == *info.fLocale && |
+ fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern); |
+} |
+ |
+ |
+CurrencyPluralInfo* |
+CurrencyPluralInfo::clone() const { |
+ return new CurrencyPluralInfo(*this); |
+} |
+ |
+const PluralRules* |
+CurrencyPluralInfo::getPluralRules() const { |
+ return fPluralRules; |
+} |
+ |
+UnicodeString& |
+CurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString& pluralCount, |
+ UnicodeString& result) const { |
+ const UnicodeString* currencyPluralPattern = |
+ (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount); |
+ if (currencyPluralPattern == NULL) { |
+ // fall back to "other" |
+ if (pluralCount.compare(gPluralCountOther)) { |
+ currencyPluralPattern = |
+ (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(gPluralCountOther); |
+ } |
+ if (currencyPluralPattern == NULL) { |
+ // no currencyUnitPatterns defined, |
+ // fallback to predefined defult. |
+ // This should never happen when ICU resource files are |
+ // available, since currencyUnitPattern of "other" is always |
+ // defined in root. |
+ result = UnicodeString(gDefaultCurrencyPluralPattern); |
+ return result; |
+ } |
+ } |
+ result = *currencyPluralPattern; |
+ return result; |
+} |
+ |
+const Locale& |
+CurrencyPluralInfo::getLocale() const { |
+ return *fLocale; |
+} |
+ |
+void |
+CurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription, |
+ UErrorCode& status) { |
+ if (U_SUCCESS(status)) { |
+ if (fPluralRules) { |
+ delete fPluralRules; |
+ } |
+ fPluralRules = PluralRules::createRules(ruleDescription, status); |
+ } |
+} |
+ |
+ |
+void |
+CurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount, |
+ const UnicodeString& pattern, |
+ UErrorCode& status) { |
+ if (U_SUCCESS(status)) { |
+ fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status); |
+ } |
+} |
+ |
+ |
+void |
+CurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) { |
+ initialize(loc, status); |
+} |
+ |
+ |
+void |
+CurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ delete fLocale; |
+ fLocale = loc.clone(); |
+ if (fPluralRules) { |
+ delete fPluralRules; |
+ } |
+ fPluralRules = PluralRules::forLocale(loc, status); |
+ setupCurrencyPluralPattern(loc, status); |
+} |
+ |
+ |
+void |
+CurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) { |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ |
+ if (fPluralCountToCurrencyUnitPattern) { |
+ deleteHash(fPluralCountToCurrencyUnitPattern); |
+ } |
+ fPluralCountToCurrencyUnitPattern = initHash(status); |
+ if (U_FAILURE(status)) { |
+ return; |
+ } |
+ |
+ UErrorCode ec = U_ZERO_ERROR; |
+ UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec); |
+ rb = ures_getByKey(rb, gNumberElementsTag, rb, &ec); |
+ rb = ures_getByKey(rb, gLatnTag, rb, &ec); |
+ rb = ures_getByKey(rb, gPatternsTag, rb, &ec); |
+ int32_t ptnLen; |
+ const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); |
+ int32_t numberStylePatternLen = ptnLen; |
+ const UChar* negNumberStylePattern = NULL; |
+ int32_t negNumberStylePatternLen = 0; |
+ // TODO: Java |
+ // parse to check whether there is ";" separator in the numberStylePattern |
+ UBool hasSeparator = false; |
+ if (U_SUCCESS(ec)) { |
+ for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) { |
+ if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) { |
+ hasSeparator = true; |
+ // split the number style pattern into positive and negative |
+ negNumberStylePattern = numberStylePattern + styleCharIndex + 1; |
+ negNumberStylePatternLen = ptnLen - styleCharIndex - 1; |
+ numberStylePatternLen = styleCharIndex; |
+ } |
+ } |
+ } |
+ ures_close(rb); |
+ |
+ if (U_FAILURE(ec)) { |
+ return; |
+ } |
+ |
+ UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec); |
+ UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec); |
+ |
+#ifdef CURRENCY_PLURAL_INFO_DEBUG |
+ std::cout << "in set up\n"; |
+#endif |
+ StringEnumeration* keywords = fPluralRules->getKeywords(ec); |
+ if (U_SUCCESS(ec)) { |
+ const char* pluralCount; |
+ while ((pluralCount = keywords->next(NULL, ec)) != NULL) { |
+ if ( U_SUCCESS(ec) ) { |
+ int32_t ptnLen; |
+ UErrorCode err = U_ZERO_ERROR; |
+ const UChar* patternChars = ures_getStringByKeyWithFallback( |
+ currencyRes, pluralCount, &ptnLen, &err); |
+ if (U_SUCCESS(err) && ptnLen > 0) { |
+ UnicodeString* pattern = new UnicodeString(patternChars, ptnLen); |
+#ifdef CURRENCY_PLURAL_INFO_DEBUG |
+ char result_1[1000]; |
+ pattern->extract(0, pattern->length(), result_1, "UTF-8"); |
+ std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; |
+#endif |
+ pattern->findAndReplace(gPart0, |
+ UnicodeString(numberStylePattern, numberStylePatternLen)); |
+ pattern->findAndReplace(gPart1, gTripleCurrencySign); |
+ |
+ if (hasSeparator) { |
+ UnicodeString negPattern(patternChars, ptnLen); |
+ negPattern.findAndReplace(gPart0, |
+ UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); |
+ negPattern.findAndReplace(gPart1, gTripleCurrencySign); |
+ pattern->append(gNumberPatternSeparator); |
+ pattern->append(negPattern); |
+ } |
+#ifdef CURRENCY_PLURAL_INFO_DEBUG |
+ pattern->extract(0, pattern->length(), result_1, "UTF-8"); |
+ std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; |
+#endif |
+ |
+ fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount), pattern, status); |
+ } |
+ } |
+ } |
+ } |
+ delete keywords; |
+ ures_close(currencyRes); |
+ ures_close(currRb); |
+} |
+ |
+ |
+ |
+void |
+CurrencyPluralInfo::deleteHash(Hashtable* hTable) |
+{ |
+ if ( hTable == NULL ) { |
+ return; |
+ } |
+ int32_t pos = -1; |
+ const UHashElement* element = NULL; |
+ while ( (element = hTable->nextElement(pos)) != NULL ) { |
+ const UHashTok keyTok = element->key; |
+ const UHashTok valueTok = element->value; |
+ const UnicodeString* value = (UnicodeString*)valueTok.pointer; |
+ delete value; |
+ } |
+ delete hTable; |
+ hTable = NULL; |
+} |
+ |
+ |
+Hashtable* |
+CurrencyPluralInfo::initHash(UErrorCode& status) { |
+ if ( U_FAILURE(status) ) { |
+ return NULL; |
+ } |
+ Hashtable* hTable; |
+ if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { |
+ status = U_MEMORY_ALLOCATION_ERROR; |
+ return NULL; |
+ } |
+ hTable->setValueComparator(ValueComparator); |
+ return hTable; |
+} |
+ |
+ |
+void |
+CurrencyPluralInfo::copyHash(const Hashtable* source, |
+ Hashtable* target, |
+ UErrorCode& status) { |
+ if ( U_FAILURE(status) ) { |
+ return; |
+ } |
+ int32_t pos = -1; |
+ const UHashElement* element = NULL; |
+ if ( source ) { |
+ while ( (element = source->nextElement(pos)) != NULL ) { |
+ const UHashTok keyTok = element->key; |
+ const UnicodeString* key = (UnicodeString*)keyTok.pointer; |
+ const UHashTok valueTok = element->value; |
+ const UnicodeString* value = (UnicodeString*)valueTok.pointer; |
+ UnicodeString* copy = new UnicodeString(*value); |
+ target->put(UnicodeString(*key), copy, status); |
+ if ( U_FAILURE(status) ) { |
+ return; |
+ } |
+ } |
+ } |
+} |
+ |
+ |
+U_NAMESPACE_END |
+ |
+#endif |
Property changes on: icu46/source/i18n/currpinf.cpp |
___________________________________________________________________ |
Added: svn:eol-style |
+ LF |