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