1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
3b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho* Copyright (C) 1997-2011, International Business Machines Corporation
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* and others. All Rights Reserved.
5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
827f654740f2a26ad62a5c155af9199af9e69b889claireho#include <typeinfo>  // for 'typeid' to work
927f654740f2a26ad62a5c155af9199af9e69b889claireho
10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/rbnf.h"
11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_HAVE_RBNF
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/normlzr.h"
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/tblcoll.h"
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucol.h"
18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uloc.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unum.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utf16.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/udata.h"
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "nfrs.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
28b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
2985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "uresimp.h"
30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// debugging
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// #define DEBUG
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef DEBUG
35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "stdio.h"
36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf"
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gPercentPercent[] =
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x25, 0x25, 0
43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* "%%" */
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// All urbnf objects are created through openRules, so we init all of the
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Unicode string constants required by rbnf, nfrs, or nfr here.
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gLenientParse[] =
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x25, 0x25, 0x6C, 0x65, 0x6E, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x70, 0x61, 0x72, 0x73, 0x65, 0x3A, 0
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* "%%lenient-parse:" */
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gSemiColon = 0x003B;
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gSemiPercent[] =
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x3B, 0x25, 0
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* ";%" */
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kSomeNumberOfBitsDiv2 22
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kHalfMaxDouble (double)(1 << kSomeNumberOfBitsDiv2)
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kMaxDouble (kHalfMaxDouble * kHalfMaxDouble)
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
6185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// Temporary workaround - when noParse is true, do noting in parse.
6285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho// TODO: We need a real fix - see #6895/#6896
6385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hostatic const char *NO_SPELLOUT_PARSE_LANGUAGES[] = { "ga", NULL };
6485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThis is a utility class. It does not use ICU's RTTI.
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruIf ICU's RTTI is needed again, you can uncomment the RTTI code and derive from UObject.
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruPlease make sure that intltest passes on Windows in Release mode,
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querusince the string pooling per compilation unit will mess up how RTTI works.
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThe RTTI code was also removed due to lack of code coverage.
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocalizationInfo : public UMemory {
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprotected:
78b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    virtual ~LocalizationInfo() {}
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t refcount;
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo() : refcount(0) {}
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* ref(void) {
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++refcount;
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return this;
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* unref(void) {
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (refcount && --refcount == 0) {
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete this;
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual UBool operator==(const LocalizationInfo* rhs) const;
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline  UBool operator!=(const LocalizationInfo* rhs) const { return !operator==(rhs); }
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfRuleSets(void) const = 0;
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getRuleSetName(int32_t index) const = 0;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfDisplayLocales(void) const = 0;
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getLocaleName(int32_t index) const = 0;
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const = 0;
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t indexForLocale(const UChar* locale) const;
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t indexForRuleSet(const UChar* ruleset) const;
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    virtual UClassID getDynamicClassID() const = 0;
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    static UClassID getStaticClassID(void);
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(LocalizationInfo)
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if both strings are NULL, this returns TRUE
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustreq(const UChar* lhs, const UChar* rhs) {
117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rhs == lhs) {
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lhs && rhs) {
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return u_strcmp(lhs, rhs) == 0;
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::operator==(const LocalizationInfo* rhs) const {
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rhs) {
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (this == rhs) {
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t rsc = getNumberOfRuleSets();
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (rsc == rhs->getNumberOfRuleSets()) {
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int i = 0; i < rsc; ++i) {
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (!streq(getRuleSetName(i), rhs->getRuleSetName(i))) {
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return FALSE;
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t dlc = getNumberOfDisplayLocales();
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (dlc == rhs->getNumberOfDisplayLocales()) {
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                for (int i = 0; i < dlc; ++i) {
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    const UChar* locale = getLocaleName(i);
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    int32_t ix = rhs->indexForLocale(locale);
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // if no locale, ix is -1, getLocaleName returns null, so streq returns false
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (!streq(locale, rhs->getLocaleName(ix))) {
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return FALSE;
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for (int j = 0; j < rsc; ++j) {
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (!streq(getDisplayName(i, j), rhs->getDisplayName(ix, j))) {
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            return FALSE;
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::indexForLocale(const UChar* locale) const {
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i < getNumberOfDisplayLocales(); ++i) {
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (streq(locale, getLocaleName(i))) {
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return i;
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::indexForRuleSet(const UChar* ruleset) const {
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleset) {
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i = 0; i < getNumberOfRuleSets(); ++i) {
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (streq(ruleset, getRuleSetName(i))) {
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return i;
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef void (*Fn_Deleter)(void*);
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass VArray {
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void** buf;
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t cap;
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t size;
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Fn_Deleter deleter;
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray() : buf(NULL), cap(0), size(0), deleter(NULL) {}
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray(Fn_Deleter del) : buf(NULL), cap(0), size(0), deleter(del) {}
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~VArray() {
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (deleter) {
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int i = 0; i < size; ++i) {
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (*deleter)(buf[i]);
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(buf);
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length() {
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return size;
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void add(void* elem, UErrorCode& status) {
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (size == cap) {
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (cap == 0) {
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap = 1;
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if (cap < 256) {
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap *= 2;
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap += 256;
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (buf == NULL) {
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    buf = (void**)uprv_malloc(cap * sizeof(void*));
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    buf = (void**)uprv_realloc(buf, cap * sizeof(void*));
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (buf == NULL) {
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // if we couldn't realloc, we leak the memory we've already allocated, but we're in deep trouble anyway
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    status = U_MEMORY_ALLOCATION_ERROR;
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                void* start = &buf[size];
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                size_t count = (cap - size) * sizeof(void*);
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_memset(start, 0, count); // fill with nulls, just because
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf[size++] = elem;
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void** release(void) {
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        void** result = buf;
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf = NULL;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cap = 0;
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        size = 0;
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return result;
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocDataParser;
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass StringLocalizationInfo : public LocalizationInfo {
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* info;
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar*** data;
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t numRuleSets;
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t numLocales;
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend class LocDataParser;
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo(UChar* i, UChar*** d, int32_t numRS, int32_t numLocs)
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : info(i), data(d), numRuleSets(numRS), numLocales(numLocs)
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static StringLocalizationInfo* create(const UnicodeString& info, UParseError& perror, UErrorCode& status);
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~StringLocalizationInfo();
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfRuleSets(void) const { return numRuleSets; }
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getRuleSetName(int32_t index) const;
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfDisplayLocales(void) const { return numLocales; }
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getLocaleName(int32_t index) const;
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const;
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    virtual UClassID getDynamicClassID() const;
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    static UClassID getStaticClassID(void);
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void init(UErrorCode& status) const;
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    OPEN_ANGLE = 0x003c, /* '<' */
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CLOSE_ANGLE = 0x003e, /* '>' */
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    COMMA = 0x002c,
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TICK = 0x0027,
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    QUOTE = 0x0022,
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SPACE = 0x0020
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Utility for parsing a localization string and returning a StringLocalizationInfo*.
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocDataParser {
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* data;
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* e;
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* p;
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar ch;
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError& pe;
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode& ec;
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocDataParser(UParseError& parseError, UErrorCode& status)
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : data(NULL), e(NULL), p(NULL), ch(0xffff), pe(parseError), ec(status) {}
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~LocDataParser() {}
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * On a successful parse, return a StringLocalizationInfo*, otherwise delete locData, set perror and status,
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * and return NULL.  The StringLocalizationInfo will adopt locData if it is created.
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo* parse(UChar* data, int32_t len);
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void inc(void) { ++p; ch = 0xffff; }
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool checkInc(UChar c) { if (p < e && (ch == c || *p == c)) { inc(); return TRUE; } return FALSE; }
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool check(UChar c) { return p < e && (ch == c || *p == c); }
316b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    void skipWhitespace(void) { while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) inc();}
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool inList(UChar c, const UChar* list) const {
318b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (*list == SPACE && PatternProps::isWhiteSpace(c)) return TRUE;
319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (*list && *list != c) ++list; return *list == c;
320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void parseError(const char* msg);
322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo* doParse(void);
324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar** nextArray(int32_t& requiredLength);
326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar*  nextString(void);
327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef DEBUG
330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ERROR(msg) parseError(msg); return NULL;
331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ERROR(msg) parseError(NULL); return NULL;
333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar DQUOTE_STOPLIST[] = {
337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    QUOTE, 0
338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar SQUOTE_STOPLIST[] = {
341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TICK, 0
342ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar NOQUOTE_STOPLIST[] = {
345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SPACE, COMMA, CLOSE_ANGLE, OPEN_ANGLE, TICK, QUOTE, 0
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDeleteFn(void* p) {
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  uprv_free(p);
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::parse(UChar* _data, int32_t len) {
355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(ec)) {
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (_data) uprv_free(_data);
357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.line = 0;
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.offset = -1;
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.postContext[0] = 0;
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.preContext[0] = 0;
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (_data == NULL) {
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len <= 0) {
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(_data);
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = _data;
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    e = data + len;
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    p = _data;
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ch = 0xffff;
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return doParse();
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::doParse(void) {
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(OPEN_ANGLE)) {
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ERROR("Missing open angle");
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        VArray array(DeleteFn);
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool mightHaveNext = TRUE;
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t requiredLength = -1;
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (mightHaveNext) {
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mightHaveNext = FALSE;
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar** elem = nextArray(requiredLength);
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            skipWhitespace();
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UBool haveComma = check(COMMA);
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (elem) {
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                array.add(elem, ec);
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (haveComma) {
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    inc();
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    mightHaveNext = TRUE;
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (haveComma) {
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Unexpected character");
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!checkInc(CLOSE_ANGLE)) {
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (check(OPEN_ANGLE)) {
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing comma in outer array");
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing close angle bracket in outer array");
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p != e) {
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Extra text after close of localization data");
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        array.add(NULL, ec);
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t numLocs = array.length() - 2; // subtract first, NULL
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar*** result = (UChar***)array.release();
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return new StringLocalizationInfo(data, result, requiredLength-2, numLocs); // subtract first, NULL
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ERROR("Unknown error");
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUChar**
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::nextArray(int32_t& requiredLength) {
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(ec)) {
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(OPEN_ANGLE)) {
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ERROR("Missing open angle");
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray array;
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool mightHaveNext = TRUE;
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (mightHaveNext) {
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mightHaveNext = FALSE;
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* elem = nextString();
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool haveComma = check(COMMA);
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (elem) {
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            array.add(elem, ec);
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (haveComma) {
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inc();
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mightHaveNext = TRUE;
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (haveComma) {
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected comma");
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(CLOSE_ANGLE)) {
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (check(OPEN_ANGLE)) {
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Missing close angle bracket in inner array");
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Missing comma in inner array");
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    array.add(NULL, ec);
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (requiredLength == -1) {
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            requiredLength = array.length() + 1;
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (array.length() != requiredLength) {
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ec = U_ILLEGAL_ARGUMENT_ERROR;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Array not of required length");
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (UChar**)array.release();
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ERROR("Unknown Error");
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUChar*
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::nextString() {
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* result = NULL;
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (p < e) {
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UChar* terminators;
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar c = *p;
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool haveQuote = c == QUOTE || c == TICK;
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (haveQuote) {
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inc();
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            terminators = c == QUOTE ? DQUOTE_STOPLIST : SQUOTE_STOPLIST;
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            terminators = NOQUOTE_STOPLIST;
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* start = p;
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (p < e && !inList(*p, terminators)) ++p;
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p == e) {
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected end of data");
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar x = *p;
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p > start) {
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ch = x;
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *p = 0x0; // terminate by writing to data
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = start; // just point into data
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (haveQuote) {
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (x != c) {
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing matching quote");
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (p == start) {
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Empty string");
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inc();
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (x == OPEN_ANGLE || x == TICK || x == QUOTE) {
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected character in string");
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // ok for there to be no next string
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::parseError(const char* /*str*/) {
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!data) {
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* start = p - U_PARSE_CONTEXT_LEN - 1;
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (start < data) {
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start = data;
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (UChar* x = p; --x >= start;) {
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!*x) {
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = x+1;
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* limit = p + U_PARSE_CONTEXT_LEN - 1;
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (limit > e) {
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        limit = e;
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_strncpy(pe.preContext, start, (int32_t)(p-start));
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.preContext[p-start] = 0;
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_strncpy(pe.postContext, p, (int32_t)(limit-p));
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.postContext[limit-p] = 0;
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.offset = (int32_t)(p - data);
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#ifdef DEBUG
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(stderr, "%s at or near character %d: ", str, p-data);
558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString msg;
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append(start, p - start);
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append((UChar)0x002f); /* SOLIDUS/SLASH */
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append(p, limit-p);
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append("'");
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char buf[128];
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = msg.extract(0, msg.length(), buf, 128);
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len >= 128) {
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf[127] = 0;
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf[len] = 0;
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(stderr, "%s\n", buf);
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fflush(stderr);
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(data);
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = NULL;
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    p = NULL;
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    e = NULL;
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_PARSE_ERROR;
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringLocalizationInfo)
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::create(const UnicodeString& info, UParseError& perror, UErrorCode& status) {
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = info.length();
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len == 0) {
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL; // no error;
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* p = (UChar*)uprv_malloc(len * sizeof(UChar));
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!p) {
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    info.extract(p, len, status);
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!U_FAILURE(status)) {
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR; // clear warning about non-termination
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocDataParser parser(perror, status);
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return parser.parse(p, len);
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::~StringLocalizationInfo() {
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (UChar*** p = (UChar***)data; *p; ++p) {
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // remaining data is simply pointer into our unicode string data.
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p) uprv_free(*p);
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (data) uprv_free(data);
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info) uprv_free(info);
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getRuleSetName(int32_t index) const {
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (index >= 0 && index < getNumberOfRuleSets()) {
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[0][index];
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getLocaleName(int32_t index) const {
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (index >= 0 && index < getNumberOfDisplayLocales()) {
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[index+1][0];
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getDisplayName(int32_t localeIndex, int32_t ruleIndex) const {
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localeIndex >= 0 && localeIndex < getNumberOfDisplayLocales() &&
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleIndex >= 0 && ruleIndex < getNumberOfRuleSets()) {
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[localeIndex+1][ruleIndex+1];
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ----------
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const UnicodeString& locs,
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
66185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  , noParse(FALSE) //TODO: to be removed after #6895
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, locinfo, perror, status);
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const UnicodeString& locs,
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             UParseError& perror, UErrorCode& status)
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(Locale::getDefault())
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
67885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  , noParse(FALSE) //TODO: to be removed after #6895
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, locinfo, perror, status);
682ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
683ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             LocalizationInfo* info,
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
688ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
689ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
690ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
694ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
69585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  , noParse(FALSE) //TODO: to be removed after #6895
696ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
697ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, info, perror, status);
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UParseError& perror,
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode& status)
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(Locale::getDefault())
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
707ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
708ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
71185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  , noParse(FALSE) //TODO: to be removed after #6895
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    init(description, NULL, perror, status);
714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const Locale& aLocale,
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UParseError& perror,
719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode& status)
720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
721ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(aLocale)
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
72885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho  , noParse(FALSE) //TODO: to be removed after #6895
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    init(description, NULL, perror, status);
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
74785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const char* rules_tag = "RBNFRules";
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char* fmt_tag = "";
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (tag) {
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break;
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break;
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_DURATION: fmt_tag = "DurationRules"; break;
75385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case URBNF_NUMBERING_SYSTEM: fmt_tag = "NumberingSystemRules"; break;
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default: status = U_ILLEGAL_ARGUMENT_ERROR; return;
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO: read localization info from resource
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* locinfo = NULL;
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = 0;
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle* nfrb = ures_open(U_ICUDATA_RBNF, locale.getName(), &status);
762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
763ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status),
764ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     ures_getLocaleByType(nfrb, ULOC_ACTUAL_LOCALE, &status));
76585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
76685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UResourceBundle* rbnfRules = ures_getByKeyWithFallback(nfrb, rules_tag, NULL, &status);
76785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
76885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(nfrb);
76985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
77085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UResourceBundle* ruleSets = ures_getByKeyWithFallback(rbnfRules, fmt_tag, NULL, &status);
77185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
77285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(rbnfRules);
77385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(nfrb);
77485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
77585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
77685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
77785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString desc;
77885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while (ures_hasNext(ruleSets)) {
77985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           const UChar* currentString = ures_getNextString(ruleSets,&len,NULL,&status);
78085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho           desc.append(currentString);
78185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UParseError perror;
78385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
78485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        init (desc, locinfo, perror, status);
78685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
78785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        //TODO: we need a real fix - see #6895 / #6896
78885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        noParse = FALSE;
78985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (tag == URBNF_SPELLOUT) {
79085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            const char *lang = alocale.getLanguage();
79185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            for (int32_t i = 0; NO_SPELLOUT_PARSE_LANGUAGES[i] != NULL; i++) {
79285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (uprv_strcmp(lang, NO_SPELLOUT_PARSE_LANGUAGES[i]) == 0) {
79385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    noParse = TRUE;
79485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                    break;
79585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
79685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            }
79785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
79885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        //TODO: end
79985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
80085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(ruleSets);
80185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(rbnfRules);
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(nfrb);
804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : NumberFormat(rhs)
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , ruleSets(NULL)
809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(rhs.locale)
811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->operator=(rhs);
818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// --------
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat&
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs)
824ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dispose();
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    locale = rhs.locale;
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenient = rhs.lenient;
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString rules = rhs.getRules();
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError perror;
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    init(rules, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
83485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //TODO: remove below when we fix the parse bug - See #6895 / #6896
83585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    noParse = rhs.noParse;
83685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::~RuleBasedNumberFormat()
841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dispose();
843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::clone(void) const
847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    RuleBasedNumberFormat * result = NULL;
849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString rules = getRules();
850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError perror;
852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = new RuleBasedNumberFormat(rules, localizations, locale, perror, status);
853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* test for NULL */
854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result == 0) {
855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return 0;
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete result;
860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result = 0;
861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        result->lenient = lenient;
86385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        //TODO: remove below when we fix the parse bug - See #6895 / #6896
86585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        result->noParse = noParse;
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::operator==(const Format& other) const
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &other) {
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
876ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
87727f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) == typeid(other)) {
878ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const RuleBasedNumberFormat& rhs = (const RuleBasedNumberFormat&)other;
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (locale == rhs.locale &&
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenient == rhs.lenient &&
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (localizations == NULL
882ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ? rhs.localizations == NULL
883ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                : (rhs.localizations == NULL
884ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ? FALSE
885ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    : *localizations == rhs.localizations))) {
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet** p = ruleSets;
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet** q = rhs.ruleSets;
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (p == NULL) {
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return q == NULL;
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (q == NULL) {
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (*p && *q && (**p == **q)) {
895ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++p;
896ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++q;
897ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
898ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return *q == NULL && *p == NULL;
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
905ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
906ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRules() const
907ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
908ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString result;
909ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets != NULL) {
910ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
911ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (*p)->appendRules(result);
912ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
913ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
914ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
915ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetName(int32_t index) const
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return string;
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (ruleSets) {
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString result;
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = *p;
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs->isPublic()) {
928ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (--index == -1) {
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    rs->getName(result);
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return result;
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString empty;
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return empty;
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
938ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
940ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getNumberOfRuleSetNames() const
941ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
942ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t result = 0;
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      result = localizations->getNumberOfRuleSets();
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else if (ruleSets) {
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((**p).isPublic()) {
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++result;
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getNumberOfRuleSetDisplayNameLocales(void) const {
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return localizations->getNumberOfDisplayLocales();
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocale
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayNameLocale(int32_t index, UErrorCode& status) const {
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return Locale("");
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations && index >= 0 && index < localizations->getNumberOfDisplayLocales()) {
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString name(TRUE, localizations->getLocaleName(index), -1);
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char buffer[64];
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t cap = name.length() + 1;
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char* bp = buffer;
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (cap > 64) {
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bp = (char *)uprv_malloc(cap);
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (bp == NULL) {
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return Locale("");
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name.extract(0, name.length(), bp, cap, UnicodeString::kInvariant);
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Locale retLocale(bp);
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (bp != buffer) {
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(bp);
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
985ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return retLocale;
986ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
987ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    status = U_ILLEGAL_ARGUMENT_ERROR;
988ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Locale retLocale;
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return retLocale;
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayName(int32_t index, const Locale& localeParam) {
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations && index >= 0 && index < localizations->getNumberOfRuleSets()) {
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString localeName(localeParam.getBaseName(), -1, UnicodeString::kInvariant);
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = localeName.length();
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* localeStr = localeName.getBuffer(len + 1);
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (len >= 0) {
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            localeStr[len] = 0;
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ix = localizations->indexForLocale(localeStr);
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ix >= 0) {
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString name(TRUE, localizations->getDisplayName(ix, index), -1);
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return name;
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // trim trailing portion, skipping over ommitted sections
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do { --len;} while (len > 0 && localeStr[len] != 0x005f); // underscore
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (len > 0 && localeStr[len-1] == 0x005F) --len;
1009ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1010ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString name(TRUE, localizations->getRuleSetName(index), -1);
1011ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return name;
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString bogus;
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bogus.setToBogus();
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return bogus;
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayName(const UnicodeString& ruleSetName, const Locale& localeParam) {
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString rsn(ruleSetName);
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t ix = localizations->indexForRuleSet(rsn.getTerminatedBuffer());
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return getRuleSetDisplayName(ix, localeParam);
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString bogus;
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bogus.setToBogus();
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return bogus;
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruNFRuleSet*
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status) const
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status) && ruleSets) {
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = *p;
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs->isNamed(name)) {
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return rs;
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int32_t number,
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */) const
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (defaultRuleSet) defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length());
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int64_t number,
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */) const
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (defaultRuleSet) defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(double number,
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */) const
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1070b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    // Special case for NaN; adapted from what DecimalFormat::_format( double number,...) does.
1071b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    if (uprv_isNaN(number)) {
1072b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        DecimalFormatSymbols* decFmtSyms = getDecimalFormatSymbols(); // RuleBasedNumberFormat internal
1073b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        if (decFmtSyms) {
1074b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            toAppendTo += decFmtSyms->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
1075b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        }
1076b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    } else if (defaultRuleSet) {
1077b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho        defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
1078b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int32_t number,
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */,
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSetName.indexOf(gPercentPercent) == 0) {
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // throw new IllegalArgumentException("Can't use internal rule set");
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet *rs = findRuleSet(ruleSetName, status);
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs) {
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rs->format((int64_t)number, toAppendTo, toAppendTo.length());
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int64_t number,
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */,
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSetName.indexOf(gPercentPercent) == 0) {
1115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // throw new IllegalArgumentException("Can't use internal rule set");
1116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet *rs = findRuleSet(ruleSetName, status);
1119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs) {
1120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rs->format(number, toAppendTo, toAppendTo.length());
1121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// make linker happy
1129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(const Formattable& obj,
1131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& pos,
1133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NumberFormat::format(obj, toAppendTo, pos, status);
1136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(double number,
1140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */,
1143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSetName.indexOf(gPercentPercent) == 0) {
1147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // throw new IllegalArgumentException("Can't use internal rule set");
1148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet *rs = findRuleSet(ruleSetName, status);
1151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs) {
1152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rs->format(number, toAppendTo, toAppendTo.length());
1153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::parse(const UnicodeString& text,
1161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             Formattable& result,
1162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             ParsePosition& parsePosition) const
1163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
116485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    //TODO: We need a real fix.  See #6895 / #6896
116585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    if (noParse) {
116685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        // skip parsing
116785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parsePosition.setErrorIndex(0);
116885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
116985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    }
117085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePosition.setErrorIndex(0);
1173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString workingText(text, parsePosition.getIndex());
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition workingPos(0);
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition high_pp(0);
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable high_result;
1181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (NFRuleSet** p = ruleSets; *p; ++p) {
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        NFRuleSet *rp = *p;
118485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (rp->isPublic() && rp->isParseable()) {
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ParsePosition working_pp(0);
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Formattable working_result;
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            rp->parse(workingText, working_pp, kMaxDouble, working_result);
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (working_pp.getIndex() > high_pp.getIndex()) {
1190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                high_pp = working_pp;
1191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                high_result = working_result;
1192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (high_pp.getIndex() == workingText.length()) {
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t startIndex = parsePosition.getIndex();
120185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parsePosition.setIndex(startIndex + high_pp.getIndex());
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (high_pp.getIndex() > 0) {
1203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePosition.setErrorIndex(-1);
120485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
120585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t errorIndex = (high_pp.getErrorIndex()>0)? high_pp.getErrorIndex(): 0;
120685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parsePosition.setErrorIndex(startIndex + errorIndex);
1207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = high_result;
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result.getType() == Formattable::kDouble) {
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t r = (int32_t)result.getDouble();
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if ((double)r == result.getDouble()) {
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.setLong(r);
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::setLenient(UBool enabled)
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenient = enabled;
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!enabled && collator) {
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete collator;
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        collator = NULL;
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::setDefaultRuleSet(const UnicodeString& ruleSetName, UErrorCode& status) {
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSetName.isEmpty()) {
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          if (localizations) {
1236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UnicodeString name(TRUE, localizations->getRuleSetName(0), -1);
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              defaultRuleSet = findRuleSet(name, status);
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          } else {
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            initDefaultRuleSet();
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          }
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (ruleSetName.startsWith(UNICODE_STRING_SIMPLE("%%"))) {
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* result = findRuleSet(ruleSetName, status);
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (result != NULL) {
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = result;
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getDefaultRuleSetName() const {
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  UnicodeString result;
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  if (defaultRuleSet && defaultRuleSet->isPublic()) {
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    defaultRuleSet->getName(result);
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  } else {
1258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result.setToBogus();
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  }
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  return result;
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::initDefaultRuleSet()
1265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    defaultRuleSet = NULL;
1267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru      return;
1269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
127185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UnicodeString spellout = UNICODE_STRING_SIMPLE("%spellout-numbering");
127285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UnicodeString ordinal = UNICODE_STRING_SIMPLE("%digits-ordinal");
127385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const UnicodeString duration = UNICODE_STRING_SIMPLE("%duration");
127485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NFRuleSet**p = &ruleSets[0];
1276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (*p) {
127785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ((*p)->isNamed(spellout) || (*p)->isNamed(ordinal) || (*p)->isNamed(duration)) {
127885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            defaultRuleSet = *p;
127985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
128085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
128185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++p;
128285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    defaultRuleSet = *--p;
1286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!defaultRuleSet->isPublic()) {
1287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (p != ruleSets) {
1288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((*--p)->isPublic()) {
1289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = *p;
1290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* localizationInfos,
1299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UParseError& pErr, UErrorCode& status)
1300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO: implement UParseError
1302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(&pErr, 0, sizeof(UParseError));
1303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Note: this can leave ruleSets == NULL, so remaining code should check
1304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->localizations = localizationInfos == NULL ? NULL : localizationInfos->ref();
1309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString description(rules);
1311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!description.length()) {
1312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // start by stripping the trailing whitespace from all the rules
1317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // (this is all the whitespace follwing each semicolon in the
1318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // description).  This allows us to look for rule-set boundaries
1319ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // by searching for ";%" without having to worry about whitespace
1320ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // between the ; and the %
1321ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    stripWhitespace(description);
1322ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1323ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // check to see if there's a set of lenient-parse rules.  If there
1324ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is, pull them out into our temporary holding place for them,
1325ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and delete them from the description before the real desciption-
1326ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // parsing code sees them
1327ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t lp = description.indexOf(gLenientParse);
1328ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lp != -1) {
1329ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we've got to make sure we're not in the middle of a rule
1330ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // (where "%%lenient-parse" would actually get treated as
1331ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rule text)
1332ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (lp == 0 || description.charAt(lp - 1) == gSemiColon) {
1333ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // locate the beginning and end of the actual collation
1334ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // rules (there may be whitespace between the name and
1335ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the first token in the description)
1336ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int lpEnd = description.indexOf(gSemiPercent, lp);
1337ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1338ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lpEnd == -1) {
1339ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                lpEnd = description.length() - 1;
1340ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1341ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int lpStart = lp + u_strlen(gLenientParse);
1342b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (PatternProps::isWhiteSpace(description.charAt(lpStart))) {
1343ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++lpStart;
1344ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1345ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // copy out the lenient-parse rules and delete them
1347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // from the description
1348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenientParseRules = new UnicodeString();
1349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* test for NULL */
1350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lenientParseRules == 0) {
1351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenientParseRules->setTo(description, lpStart, lpEnd - lpStart);
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            description.remove(lp, lpEnd + 1 - lp);
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pre-flight parsing the description and count the number of
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // rule sets (";%" marks the end of one rule set and the beginning
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // of the next)
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int numRuleSets = 0;
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int32_t p = description.indexOf(gSemiPercent); p != -1; p = description.indexOf(gSemiPercent, p)) {
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++numRuleSets;
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++p;
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ++numRuleSets;
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // our rule list is an array of the appropriate size
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ruleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *));
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* test for NULL */
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets == 0) {
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i <= numRuleSets; ++i) {
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSets[i] = NULL;
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // divide up the descriptions into individual rule-set descriptions
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and store them in a temporary array.  At each step, we also
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // new up a rule set, but all this does is initialize its name
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and remove it from its description.  We can't actually parse
1386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the rest of the descriptions and finish initializing everything
1387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // because we have to know the names and locations of all the rule
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // sets before we can actually set everything up
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!numRuleSets) {
139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        status = U_ILLEGAL_ARGUMENT_ERROR;
139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
1392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString* ruleSetDescriptions = new UnicodeString[numRuleSets];
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSetDescriptions == 0) {
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int curRuleSet = 0;
1401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t start = 0;
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int32_t p = description.indexOf(gSemiPercent); p != -1; p = description.indexOf(gSemiPercent, start)) {
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ruleSets[curRuleSet] == 0) {
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
140785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                goto cleanup;
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++curRuleSet;
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = p + 1;
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start);
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSets[curRuleSet] == 0) {
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
141685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            goto cleanup;
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // now we can take note of the formatter's default rule set, which
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is the last public rule set in the description (it's the last
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // rather than the first so that a user can create a new formatter
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // from an existing formatter and change its default behavior just
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // by appending more rule sets to the end)
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {dlf} Initialization of a fraction rule set requires the default rule
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set to be known.  For purposes of initialization, this is always the
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // last public rule set, no matter what the localization data says.
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initDefaultRuleSet();
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // finally, we can go back through the temporary descriptions
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // list and finish seting up the substructure (and we throw
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // away the temporary descriptions as we go)
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i = 0; i < numRuleSets; i++) {
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Now that the rules are initialized, the 'real' default rule
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set can be adjusted by the localization data.
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The C code keeps the localization array as is, rather than building
1444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a separate array of the public rule set names, so we have less work
1445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // to do here-- but we still need to check the names.
1446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizationInfos) {
1448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // confirm the names, if any aren't in the rules, that's an error
1449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // it is ok if the rules contain public rule sets that are not in this list
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int32_t i = 0; i < localizationInfos->getNumberOfRuleSets(); ++i) {
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UnicodeString name(TRUE, localizationInfos->getRuleSetName(i), -1);
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = findRuleSet(name, status);
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs == NULL) {
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break; // error
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
1457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = rs;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        defaultRuleSet = getDefaultRuleSet();
1462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
146385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
146485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Hocleanup:
146585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    delete[] ruleSetDescriptions;
1466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::stripWhitespace(UnicodeString& description)
1470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // iterate through the characters...
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString result;
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int start = 0;
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (start != -1 && start < description.length()) {
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // seek to the first non-whitespace character...
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (start < description.length()
1478b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            && PatternProps::isWhiteSpace(description.charAt(start))) {
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++start;
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // locate the next semicolon in the text and copy the text from
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // our current position up to that semicolon into the result
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t p = description.indexOf(gSemiColon, start);
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p == -1) {
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // or if we don't find a semicolon, just copy the rest of
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the string into the result
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.append(description, start, description.length() - start);
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = -1;
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (p < description.length()) {
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.append(description, start, p + 1 - start);
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = p + 1;
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // when we get here, we've seeked off the end of the sring, and
1497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we terminate the loop (we continue until *start* is -1 rather
1498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // than until *p* is -1, because otherwise we'd miss the last
1499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rule in the description)
1500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = -1;
1502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    description.setTo(result);
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::dispose()
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets) {
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete *p;
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(ruleSets);
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSets = NULL;
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete collator;
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    collator = NULL;
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete decimalFormatSymbols;
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    decimalFormatSymbols = NULL;
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete lenientParseRules;
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenientParseRules = NULL;
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) localizations = localizations->unref();
1532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//-----------------------------------------------------------------------
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// package-internal API
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//-----------------------------------------------------------------------
1538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the collator to use for lenient parsing.  The collator is lazily created:
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * this function creates it the first time it's called.
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The collator to use for lenient parsing, or null if lenient parsing
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is turned off.
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruCollator*
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getCollator() const
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // lazy-evaulate the collator
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (collator == NULL && lenient) {
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // create a default collator based on the formatter's locale,
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // then pull out that collator's rules, append any additional
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rules specified in the description, and create a _new_
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // collator based on the combinaiton of those rules
1559ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Collator* temp = Collator::createInstance(locale, status);
156327f654740f2a26ad62a5c155af9199af9e69b889claireho        RuleBasedCollator* newCollator;
156427f654740f2a26ad62a5c155af9199af9e69b889claireho        if (U_SUCCESS(status) && (newCollator = dynamic_cast<RuleBasedCollator*>(temp)) != NULL) {
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lenientParseRules) {
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString rules(newCollator->getRules());
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rules.append(*lenientParseRules);
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                newCollator = new RuleBasedCollator(rules, status);
157085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // Exit if newCollator could not be created.
157185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (newCollator == NULL) {
157285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                	return NULL;
157385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                temp = NULL;
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_SUCCESS(status)) {
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                newCollator->setAttribute(UCOL_DECOMPOSITION_MODE, UCOL_ON, status);
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // cast away const
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ((RuleBasedNumberFormat*)this)->collator = newCollator;
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete newCollator;
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete temp;
1586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if lenient-parse mode is off, this will be null
1590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // (see setLenientParseMode())
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return collator;
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * instances owned by this formatter.  This object is lazily created: this function
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * creates it the first time it's called.
1599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The DecimalFormatSymbols object that should be used by all DecimalFormat
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * instances owned by this formatter.
1601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDecimalFormatSymbols*
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getDecimalFormatSymbols() const
1604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // lazy-evaluate the DecimalFormatSymbols object.  This object
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is shared by all DecimalFormat instances belonging to this
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // formatter
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (decimalFormatSymbols == NULL) {
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
1610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status);
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ((RuleBasedNumberFormat*)this)->decimalFormatSymbols = temp;
1613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete temp;
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return decimalFormatSymbols;
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* U_HAVE_RBNF */
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1624