1b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/* 2b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ******************************************************************************* 3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho * Copyright (C) 2009-2011, International Business Machines Corporation and 450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho * others. All Rights Reserved. 5b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ******************************************************************************* 6b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 7b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 8b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/currpinf.h" 9b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 10b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 11b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 12b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru//#define CURRENCY_PLURAL_INFO_DEBUG 1 13b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 14b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef CURRENCY_PLURAL_INFO_DEBUG 15b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include <iostream> 16b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 17b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 18b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 19b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/locid.h" 20b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/plurrule.h" 21b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "unicode/ures.h" 22b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "cstring.h" 23b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "hash.h" 24b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#include "uresimp.h" 2550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho#include "ureslocs.h" 26b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 27b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_NAMESPACE_BEGIN 28b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 29b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 30b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gNumberPatternSeparator = 0x3B; // ; 31b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 32b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CDECL_BEGIN 33b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 34b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru/** 35b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru * @internal ICU 4.2 36b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru */ 37b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic UBool U_CALLCONV ValueComparator(UHashTok val1, UHashTok val2); 38b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 39b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUBool 40b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_CALLCONV ValueComparator(UHashTok val1, UHashTok val2) { 41b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* affix_1 = (UnicodeString*)val1.pointer; 42b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* affix_2 = (UnicodeString*)val2.pointer; 43b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *affix_1 == *affix_2; 44b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 45b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 4650294ead5e5d23f5bbfed76e00e6b510bd41eee1clairehoU_CDECL_END 47b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 48b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 49b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(CurrencyPluralInfo) 50b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 51b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gDefaultCurrencyPluralPattern[] = {'0', '.', '#', '#', ' ', 0xA4, 0xA4, 0xA4, 0}; 52b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gTripleCurrencySign[] = {0xA4, 0xA4, 0xA4, 0}; 53b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gPluralCountOther[] = {0x6F, 0x74, 0x68, 0x65, 0x72, 0}; 54b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gPart0[] = {0x7B, 0x30, 0x7D, 0}; 55b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const UChar gPart1[] = {0x7B, 0x31, 0x7D, 0}; 56b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 5727f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gNumberElementsTag[]="NumberElements"; 5827f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gLatnTag[]="latn"; 5927f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gPatternsTag[]="patterns"; 6027f654740f2a26ad62a5c155af9199af9e69b889clairehostatic const char gDecimalFormatTag[]="decimalFormat"; 61b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Querustatic const char gCurrUnitPtnTag[]="CurrencyUnitPatterns"; 62b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 63b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::CurrencyPluralInfo(UErrorCode& status) 64b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru: fPluralCountToCurrencyUnitPattern(NULL), 65b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules(NULL), 66b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale(NULL) { 67b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initialize(Locale::getDefault(), status); 68b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 69b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 70b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::CurrencyPluralInfo(const Locale& locale, UErrorCode& status) 71b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru: fPluralCountToCurrencyUnitPattern(NULL), 72b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules(NULL), 73b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale(NULL) { 74b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initialize(locale, status); 75b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 76b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 77b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::CurrencyPluralInfo(const CurrencyPluralInfo& info) 78b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru: UObject(info), 79b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern(NULL), 80b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules(NULL), 81b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale(NULL) { 82b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *this = info; 83b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 84b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 85b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 86b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo& 87b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::operator=(const CurrencyPluralInfo& info) { 88b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (this == &info) { 89b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *this; 90b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 91b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 92b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru deleteHash(fPluralCountToCurrencyUnitPattern); 93b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode status = U_ZERO_ERROR; 94b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern = initHash(status); 95b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru copyHash(info.fPluralCountToCurrencyUnitPattern, 96b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern, status); 97b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( U_FAILURE(status) ) { 98b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *this; 99b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 100b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 101b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fPluralRules; 102b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fLocale; 103b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (info.fPluralRules) { 104b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules = info.fPluralRules->clone(); 105b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 106b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules = NULL; 107b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 108b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (info.fLocale) { 109b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale = info.fLocale->clone(); 110b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } else { 111b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale = NULL; 112b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 113b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *this; 114b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 115b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 116b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 117b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::~CurrencyPluralInfo() { 118b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru deleteHash(fPluralCountToCurrencyUnitPattern); 119b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern = NULL; 120b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fPluralRules; 121b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fLocale; 122b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules = NULL; 123b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale = NULL; 124b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 125b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 126b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUBool 127b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::operator==(const CurrencyPluralInfo& info) const { 128b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef CURRENCY_PLURAL_INFO_DEBUG 129b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*fPluralRules == *info.fPluralRules) { 130b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "same plural rules\n"; 131b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 132b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (*fLocale == *info.fLocale) { 133b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "same locale\n"; 134b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 135b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern)) { 136b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "same pattern\n"; 137b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 138b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 139b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *fPluralRules == *info.fPluralRules && 140b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru *fLocale == *info.fLocale && 141b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern->equals(*info.fPluralCountToCurrencyUnitPattern); 142b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 143b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 144b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 145b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo* 146b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::clone() const { 147b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return new CurrencyPluralInfo(*this); 148b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 149b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 150b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst PluralRules* 151b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::getPluralRules() const { 152b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return fPluralRules; 153b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 154b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 155b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruUnicodeString& 156b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::getCurrencyPluralPattern(const UnicodeString& pluralCount, 157b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString& result) const { 158b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* currencyPluralPattern = 159b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(pluralCount); 160b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (currencyPluralPattern == NULL) { 161b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // fall back to "other" 162b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if (pluralCount.compare(gPluralCountOther, 5)) { 163b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru currencyPluralPattern = 164b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho (UnicodeString*)fPluralCountToCurrencyUnitPattern->get(UnicodeString(TRUE, gPluralCountOther, 5)); 165b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 166b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (currencyPluralPattern == NULL) { 167b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // no currencyUnitPatterns defined, 168b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // fallback to predefined defult. 169b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // This should never happen when ICU resource files are 170b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // available, since currencyUnitPattern of "other" is always 171b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // defined in root. 172b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru result = UnicodeString(gDefaultCurrencyPluralPattern); 173b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return result; 174b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 175b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 176b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru result = *currencyPluralPattern; 177b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return result; 178b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 179b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 180b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruconst Locale& 181b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::getLocale() const { 182b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return *fLocale; 183b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 184b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 185b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 186b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::setPluralRules(const UnicodeString& ruleDescription, 187b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode& status) { 188b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(status)) { 18950294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fPluralRules) { 19050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete fPluralRules; 19150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 192b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules = PluralRules::createRules(ruleDescription, status); 193b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 194b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 195b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 196b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 197b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 198b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::setCurrencyPluralPattern(const UnicodeString& pluralCount, 199b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString& pattern, 200b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode& status) { 201b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(status)) { 202b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern->put(pluralCount, new UnicodeString(pattern), status); 203b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 204b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 205b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 206b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 207b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 208b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::setLocale(const Locale& loc, UErrorCode& status) { 209b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru initialize(loc, status); 210b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 211b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 212b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 213b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 214b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::initialize(const Locale& loc, UErrorCode& status) { 215b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 216b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 217b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 218b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete fLocale; 219b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fLocale = loc.clone(); 22050294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fPluralRules) { 22150294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho delete fPluralRules; 22250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 223b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralRules = PluralRules::forLocale(loc, status); 224b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru setupCurrencyPluralPattern(loc, status); 225b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 226b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 227b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 228b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 229b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::setupCurrencyPluralPattern(const Locale& loc, UErrorCode& status) { 230b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 231b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 232b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 233b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 23450294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho if (fPluralCountToCurrencyUnitPattern) { 23550294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho deleteHash(fPluralCountToCurrencyUnitPattern); 23650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho } 237b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru fPluralCountToCurrencyUnitPattern = initHash(status); 238b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(status)) { 239b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 240b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 241b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 242b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode ec = U_ZERO_ERROR; 243b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UResourceBundle *rb = ures_open(NULL, loc.getName(), &ec); 244b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho rb = ures_getByKeyWithFallback(rb, gNumberElementsTag, rb, &ec); 245b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho rb = ures_getByKeyWithFallback(rb, gLatnTag, rb, &ec); 246b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho rb = ures_getByKeyWithFallback(rb, gPatternsTag, rb, &ec); 247b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t ptnLen; 24827f654740f2a26ad62a5c155af9199af9e69b889claireho const UChar* numberStylePattern = ures_getStringByKeyWithFallback(rb, gDecimalFormatTag, &ptnLen, &ec); 249b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t numberStylePatternLen = ptnLen; 250b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar* negNumberStylePattern = NULL; 251b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t negNumberStylePatternLen = 0; 252b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // TODO: Java 253b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru // parse to check whether there is ";" separator in the numberStylePattern 254b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UBool hasSeparator = false; 2556d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru if (U_SUCCESS(ec)) { 2566d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru for (int32_t styleCharIndex = 0; styleCharIndex < ptnLen; ++styleCharIndex) { 2576d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru if (numberStylePattern[styleCharIndex] == gNumberPatternSeparator) { 2586d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru hasSeparator = true; 2596d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru // split the number style pattern into positive and negative 2606d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru negNumberStylePattern = numberStylePattern + styleCharIndex + 1; 2616d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru negNumberStylePatternLen = ptnLen - styleCharIndex - 1; 2626d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru numberStylePatternLen = styleCharIndex; 2636d5deb12725f146643d443090dfa11b206df528aJean-Baptiste Queru } 264b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 265b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 26650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(rb); 267b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 268b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_FAILURE(ec)) { 269b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 270b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 271b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 27250294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *currRb = ures_open(U_ICUDATA_CURR, loc.getName(), &ec); 27350294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho UResourceBundle *currencyRes = ures_getByKeyWithFallback(currRb, gCurrUnitPtnTag, NULL, &ec); 274b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 275b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef CURRENCY_PLURAL_INFO_DEBUG 276b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "in set up\n"; 277b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 278b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru StringEnumeration* keywords = fPluralRules->getKeywords(ec); 279b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(ec)) { 280b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const char* pluralCount; 281b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ((pluralCount = keywords->next(NULL, ec)) != NULL) { 282b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( U_SUCCESS(ec) ) { 283b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t ptnLen; 284b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode err = U_ZERO_ERROR; 285b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UChar* patternChars = ures_getStringByKeyWithFallback( 286b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru currencyRes, pluralCount, &ptnLen, &err); 287b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (U_SUCCESS(err) && ptnLen > 0) { 288b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString* pattern = new UnicodeString(patternChars, ptnLen); 289b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef CURRENCY_PLURAL_INFO_DEBUG 290b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru char result_1[1000]; 291b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pattern->extract(0, pattern->length(), result_1, "UTF-8"); 292b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; 293b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 294b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pattern->findAndReplace(UnicodeString(TRUE, gPart0, 3), 295b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString(numberStylePattern, numberStylePatternLen)); 296b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho pattern->findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); 297b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 298b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if (hasSeparator) { 299b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString negPattern(patternChars, ptnLen); 300b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho negPattern.findAndReplace(UnicodeString(TRUE, gPart0, 3), 301b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString(negNumberStylePattern, negNumberStylePatternLen)); 302b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho negPattern.findAndReplace(UnicodeString(TRUE, gPart1, 3), UnicodeString(TRUE, gTripleCurrencySign, 3)); 303b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pattern->append(gNumberPatternSeparator); 304b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pattern->append(negPattern); 305b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 306b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#ifdef CURRENCY_PLURAL_INFO_DEBUG 307b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru pattern->extract(0, pattern->length(), result_1, "UTF-8"); 308b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru std::cout << "pluralCount: " << pluralCount << "; pattern: " << result_1 << "\n"; 309b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 310b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 311b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho fPluralCountToCurrencyUnitPattern->put(UnicodeString(pluralCount, -1, US_INV), pattern, status); 312b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 313b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 314b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 315b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 316b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete keywords; 317b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru ures_close(currencyRes); 31850294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho ures_close(currRb); 319b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 320b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 321b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 322b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 323b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 324b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::deleteHash(Hashtable* hTable) 325b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru{ 326b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( hTable == NULL ) { 327b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 328b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 329b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t pos = -1; 330b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashElement* element = NULL; 331b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ( (element = hTable->nextElement(pos)) != NULL ) { 332b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashTok keyTok = element->key; 333b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashTok valueTok = element->value; 334b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* value = (UnicodeString*)valueTok.pointer; 335b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete value; 336b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 337b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru delete hTable; 338b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru hTable = NULL; 339b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 340b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 341b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 342b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruHashtable* 343b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::initHash(UErrorCode& status) { 344b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( U_FAILURE(status) ) { 345b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 346b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 347b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru Hashtable* hTable; 348b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( (hTable = new Hashtable(TRUE, status)) == NULL ) { 349b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru status = U_MEMORY_ALLOCATION_ERROR; 350b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return NULL; 351b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 352b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho if ( U_FAILURE(status) ) { 353b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho delete hTable; 354b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho return NULL; 355b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho } 35650294ead5e5d23f5bbfed76e00e6b510bd41eee1claireho hTable->setValueComparator(ValueComparator); 357b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return hTable; 358b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 359b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 360b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 361b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queruvoid 362b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruCurrencyPluralInfo::copyHash(const Hashtable* source, 363b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru Hashtable* target, 364b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UErrorCode& status) { 365b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( U_FAILURE(status) ) { 366b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 367b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 368b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru int32_t pos = -1; 369b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashElement* element = NULL; 370b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( source ) { 371b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru while ( (element = source->nextElement(pos)) != NULL ) { 372b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashTok keyTok = element->key; 373b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* key = (UnicodeString*)keyTok.pointer; 374b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UHashTok valueTok = element->value; 375b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru const UnicodeString* value = (UnicodeString*)valueTok.pointer; 376b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru UnicodeString* copy = new UnicodeString(*value); 377b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru target->put(UnicodeString(*key), copy, status); 378b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru if ( U_FAILURE(status) ) { 379b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru return; 380b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 381b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 382b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru } 383b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru} 384b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 385b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 386b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste QueruU_NAMESPACE_END 387b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru 388b0ac937921a2c196d8b9da665135bf6ba01a1ccfJean-Baptiste Queru#endif 389