10596faeddefbf198de137d5e893708495ab1584cFredrik Roubert// © 2016 and later: Unicode, Inc. and others.
264339d36f8bd4db5025fe2988eda22b491a9219cFredrik Roubert// License & terms of use: http://www.unicode.org/copyright.html
3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
5c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert* Copyright (C) 1997-2015, International Business Machines Corporation
6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* and others. All Rights Reserved.
7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*******************************************************************************
8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
10fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/utypes.h"
1154dcd9b6a06071f647dac967e9e267abb9410720Craig Cornelius#include "utypeinfo.h"  // for 'typeid' to work
1227f654740f2a26ad62a5c155af9199af9e69b889claireho
13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/rbnf.h"
14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if U_HAVE_RBNF
16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/normlzr.h"
18f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#include "unicode/plurfmt.h"
19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/tblcoll.h"
20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uchar.h"
21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ucol.h"
22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/uloc.h"
23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/unum.h"
24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ures.h"
25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/ustring.h"
26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utf16.h"
27ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/udata.h"
28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/udisplaycontext.h"
29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/brkiter.h"
300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include "unicode/ucasemap.h"
31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cmemory.h"
33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "cstring.h"
34b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho#include "patternprops.h"
3585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho#include "uresimp.h"
360596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include "nfrs.h"
370596faeddefbf198de137d5e893708495ab1584cFredrik Roubert#include "digitlst.h"
38ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// debugging
40f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius// #define RBNF_DEBUG
41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
42f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#ifdef RBNF_DEBUG
43c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert#include <stdio.h>
44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf"
47ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gPercentPercent[] =
49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x25, 0x25, 0
51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* "%%" */
52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// All urbnf objects are created through openRules, so we init all of the
54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Unicode string constants required by rbnf, nfrs, or nfr here.
55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gLenientParse[] =
56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x25, 0x25, 0x6C, 0x65, 0x6E, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x70, 0x61, 0x72, 0x73, 0x65, 0x3A, 0
58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* "%%lenient-parse:" */
59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gSemiColon = 0x003B;
60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar gSemiPercent[] =
61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    0x3B, 0x25, 0
63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; /* ";%" */
64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kSomeNumberOfBitsDiv2 22
66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kHalfMaxDouble (double)(1 << kSomeNumberOfBitsDiv2)
67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define kMaxDouble (kHalfMaxDouble * kHalfMaxDouble)
68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN
70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/*
74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThis is a utility class. It does not use ICU's RTTI.
75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruIf ICU's RTTI is needed again, you can uncomment the RTTI code and derive from UObject.
76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruPlease make sure that intltest passes on Windows in Release mode,
77ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querusince the string pooling per compilation unit will mess up how RTTI works.
78ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruThe RTTI code was also removed due to lack of code coverage.
79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
80ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocalizationInfo : public UMemory {
81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprotected:
82103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    virtual ~LocalizationInfo();
83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uint32_t refcount;
84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
86ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo() : refcount(0) {}
87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* ref(void) {
89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++refcount;
90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return this;
91ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* unref(void) {
94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (refcount && --refcount == 0) {
95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete this;
96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual UBool operator==(const LocalizationInfo* rhs) const;
101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    inline  UBool operator!=(const LocalizationInfo* rhs) const { return !operator==(rhs); }
102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfRuleSets(void) const = 0;
104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getRuleSetName(int32_t index) const = 0;
105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfDisplayLocales(void) const = 0;
106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getLocaleName(int32_t index) const = 0;
107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const = 0;
108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t indexForLocale(const UChar* locale) const;
110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t indexForRuleSet(const UChar* ruleset) const;
111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    virtual UClassID getDynamicClassID() const = 0;
113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    static UClassID getStaticClassID(void);
114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
116103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusLocalizationInfo::~LocalizationInfo() {}
117103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(LocalizationInfo)
119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// if both strings are NULL, this returns TRUE
121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic UBool
122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustreq(const UChar* lhs, const UChar* rhs) {
123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rhs == lhs) {
124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
125ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
126ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lhs && rhs) {
127ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return u_strcmp(lhs, rhs) == 0;
128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
129ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
130ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
131ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
132ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
133ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::operator==(const LocalizationInfo* rhs) const {
134ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (rhs) {
135ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (this == rhs) {
136ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return TRUE;
137ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
138ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
139ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t rsc = getNumberOfRuleSets();
140ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (rsc == rhs->getNumberOfRuleSets()) {
141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int i = 0; i < rsc; ++i) {
142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (!streq(getRuleSetName(i), rhs->getRuleSetName(i))) {
143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return FALSE;
144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
145ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t dlc = getNumberOfDisplayLocales();
147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (dlc == rhs->getNumberOfDisplayLocales()) {
148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                for (int i = 0; i < dlc; ++i) {
149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    const UChar* locale = getLocaleName(i);
150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    int32_t ix = rhs->indexForLocale(locale);
151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // if no locale, ix is -1, getLocaleName returns null, so streq returns false
152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    if (!streq(locale, rhs->getLocaleName(ix))) {
153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        return FALSE;
154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    for (int j = 0; j < rsc; ++j) {
156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        if (!streq(getDisplayName(i, j), rhs->getDisplayName(ix, j))) {
157ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            return FALSE;
158ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                        }
159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    }
160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return TRUE;
162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
163ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::indexForLocale(const UChar* locale) const {
170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i < getNumberOfDisplayLocales(); ++i) {
171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (streq(locale, getLocaleName(i))) {
172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return i;
173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocalizationInfo::indexForRuleSet(const UChar* ruleset) const {
180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleset) {
181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i = 0; i < getNumberOfRuleSets(); ++i) {
182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (streq(ruleset, getRuleSetName(i))) {
183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return i;
184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return -1;
188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
191ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querutypedef void (*Fn_Deleter)(void*);
192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
193ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass VArray {
194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void** buf;
195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t cap;
196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t size;
197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Fn_Deleter deleter;
198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray() : buf(NULL), cap(0), size(0), deleter(NULL) {}
200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray(Fn_Deleter del) : buf(NULL), cap(0), size(0), deleter(del) {}
202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~VArray() {
204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (deleter) {
205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            for (int i = 0; i < size; ++i) {
206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                (*deleter)(buf[i]);
207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(buf);
210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t length() {
213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return size;
214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void add(void* elem, UErrorCode& status) {
217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (size == cap) {
219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (cap == 0) {
220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap = 1;
221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else if (cap < 256) {
222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap *= 2;
223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    cap += 256;
225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (buf == NULL) {
227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    buf = (void**)uprv_malloc(cap * sizeof(void*));
228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                } else {
229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    buf = (void**)uprv_realloc(buf, cap * sizeof(void*));
230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (buf == NULL) {
232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    // if we couldn't realloc, we leak the memory we've already allocated, but we're in deep trouble anyway
233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    status = U_MEMORY_ALLOCATION_ERROR;
234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return;
235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                void* start = &buf[size];
237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                size_t count = (cap - size) * sizeof(void*);
238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                uprv_memset(start, 0, count); // fill with nulls, just because
239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            buf[size++] = elem;
241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void** release(void) {
245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        void** result = buf;
246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf = NULL;
247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        cap = 0;
248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        size = 0;
249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return result;
250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocDataParser;
254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass StringLocalizationInfo : public LocalizationInfo {
256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* info;
257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar*** data;
258ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t numRuleSets;
259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t numLocales;
260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querufriend class LocDataParser;
262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo(UChar* i, UChar*** d, int32_t numRS, int32_t numLocs)
264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : info(i), data(d), numRuleSets(numRS), numLocales(numLocs)
265ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
266ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
267ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
268ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
269ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    static StringLocalizationInfo* create(const UnicodeString& info, UParseError& perror, UErrorCode& status);
270ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
271ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual ~StringLocalizationInfo();
272ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfRuleSets(void) const { return numRuleSets; }
273ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getRuleSetName(int32_t index) const;
274ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual int32_t getNumberOfDisplayLocales(void) const { return numLocales; }
275ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getLocaleName(int32_t index) const;
276ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const;
277ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
278ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    virtual UClassID getDynamicClassID() const;
279ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//    static UClassID getStaticClassID(void);
280ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
281ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
282ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void init(UErrorCode& status) const;
283ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
284ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
285ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruenum {
287ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    OPEN_ANGLE = 0x003c, /* '<' */
288ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    CLOSE_ANGLE = 0x003e, /* '>' */
289ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    COMMA = 0x002c,
290ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TICK = 0x0027,
291ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    QUOTE = 0x0022,
292ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SPACE = 0x0020
293ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
294ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
295ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
296ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Utility for parsing a localization string and returning a StringLocalizationInfo*.
297ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */
298ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruclass LocDataParser {
299ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* data;
300ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* e;
301ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* p;
302ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar ch;
303ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError& pe;
304ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode& ec;
305ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
306ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querupublic:
307ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocDataParser(UParseError& parseError, UErrorCode& status)
308ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        : data(NULL), e(NULL), p(NULL), ch(0xffff), pe(parseError), ec(status) {}
309ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ~LocDataParser() {}
310ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
311ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /*
312ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * On a successful parse, return a StringLocalizationInfo*, otherwise delete locData, set perror and status,
313ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    * and return NULL.  The StringLocalizationInfo will adopt locData if it is created.
314ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    */
315ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo* parse(UChar* data, int32_t len);
316ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
317ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruprivate:
318ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
319ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    inline void inc(void) {
320ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        ++p;
321ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        ch = 0xffff;
322ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
323ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    inline UBool checkInc(UChar c) {
324ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        if (p < e && (ch == c || *p == c)) {
325ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            inc();
326ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            return TRUE;
327ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        }
328ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        return FALSE;
329ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
330ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    inline UBool check(UChar c) {
331ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        return p < e && (ch == c || *p == c);
332ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
333ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    inline void skipWhitespace(void) {
334ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) {
335ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            inc();
336ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        }
337ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
338ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    inline UBool inList(UChar c, const UChar* list) const {
339ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        if (*list == SPACE && PatternProps::isWhiteSpace(c)) {
340ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            return TRUE;
341ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        }
342ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        while (*list && *list != c) {
343ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert            ++list;
344ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        }
345ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        return *list == c;
346ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
347ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    void parseError(const char* msg);
348ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
349ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    StringLocalizationInfo* doParse(void);
350ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
351ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar** nextArray(int32_t& requiredLength);
352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar*  nextString(void);
353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
355f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#ifdef RBNF_DEBUG
356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ERROR(msg) parseError(msg); return NULL;
357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define EXPLANATION_ARG explanationArg
358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else
359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define ERROR(msg) parseError(NULL); return NULL;
360fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define EXPLANATION_ARG
361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar DQUOTE_STOPLIST[] = {
365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    QUOTE, 0
366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar SQUOTE_STOPLIST[] = {
369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    TICK, 0
370ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic const UChar NOQUOTE_STOPLIST[] = {
373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    SPACE, COMMA, CLOSE_ANGLE, OPEN_ANGLE, TICK, QUOTE, 0
374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru};
375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustatic void
377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDeleteFn(void* p) {
378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  uprv_free(p);
379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::parse(UChar* _data, int32_t len) {
383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(ec)) {
384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (_data) uprv_free(_data);
385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
386ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
387ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.line = 0;
389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.offset = -1;
390ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.postContext[0] = 0;
391ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.preContext[0] = 0;
392ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (_data == NULL) {
394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
396ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
397ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
398ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len <= 0) {
399ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_ILLEGAL_ARGUMENT_ERROR;
400ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(_data);
401ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = _data;
405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    e = data + len;
406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    p = _data;
407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ch = 0xffff;
408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return doParse();
410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::doParse(void) {
415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(OPEN_ANGLE)) {
417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ERROR("Missing open angle");
418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        VArray array(DeleteFn);
420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool mightHaveNext = TRUE;
421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t requiredLength = -1;
422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (mightHaveNext) {
423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            mightHaveNext = FALSE;
424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar** elem = nextArray(requiredLength);
425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            skipWhitespace();
426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UBool haveComma = check(COMMA);
427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (elem) {
428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                array.add(elem, ec);
429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (haveComma) {
430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    inc();
431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    mightHaveNext = TRUE;
432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (haveComma) {
434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Unexpected character");
435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!checkInc(CLOSE_ANGLE)) {
440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (check(OPEN_ANGLE)) {
441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing comma in outer array");
442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
443ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing close angle bracket in outer array");
444ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
445ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
446ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
447ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
448ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p != e) {
449ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Extra text after close of localization data");
450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        array.add(NULL, ec);
453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(ec)) {
454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t numLocs = array.length() - 2; // subtract first, NULL
455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UChar*** result = (UChar***)array.release();
456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
457ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return new StringLocalizationInfo(data, result, requiredLength-2, numLocs); // subtract first, NULL
458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
460ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
461ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ERROR("Unknown error");
462ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
463ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUChar**
465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::nextArray(int32_t& requiredLength) {
466ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(ec)) {
467ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
468ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
469ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
470ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
471ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(OPEN_ANGLE)) {
472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ERROR("Missing open angle");
473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    VArray array;
476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UBool mightHaveNext = TRUE;
477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (mightHaveNext) {
478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        mightHaveNext = FALSE;
479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* elem = nextString();
480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        skipWhitespace();
481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool haveComma = check(COMMA);
482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (elem) {
483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            array.add(elem, ec);
484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (haveComma) {
485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                inc();
486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                mightHaveNext = TRUE;
487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (haveComma) {
489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected comma");
490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!checkInc(CLOSE_ANGLE)) {
494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (check(OPEN_ANGLE)) {
495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Missing close angle bracket in inner array");
496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
497ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Missing comma in inner array");
498ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
499ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
500ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
501ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    array.add(NULL, ec);
502ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
503ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (requiredLength == -1) {
504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            requiredLength = array.length() + 1;
505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (array.length() != requiredLength) {
506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ec = U_ILLEGAL_ARGUMENT_ERROR;
507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Array not of required length");
508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return (UChar**)array.release();
511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ERROR("Unknown Error");
513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUChar*
516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocDataParser::nextString() {
517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* result = NULL;
518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    skipWhitespace();
520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (p < e) {
521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const UChar* terminators;
522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar c = *p;
523ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UBool haveQuote = c == QUOTE || c == TICK;
524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (haveQuote) {
525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inc();
526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            terminators = c == QUOTE ? DQUOTE_STOPLIST : SQUOTE_STOPLIST;
527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            terminators = NOQUOTE_STOPLIST;
529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* start = p;
531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (p < e && !inList(*p, terminators)) ++p;
532ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p == e) {
533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected end of data");
534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar x = *p;
537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p > start) {
538ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ch = x;
539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            *p = 0x0; // terminate by writing to data
540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result = start; // just point into data
541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (haveQuote) {
543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (x != c) {
544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Missing matching quote");
545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (p == start) {
546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ERROR("Empty string");
547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            inc();
549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (x == OPEN_ANGLE || x == TICK || x == QUOTE) {
550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ERROR("Unexpected character in string");
551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // ok for there to be no next string
555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
558fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid LocDataParser::parseError(const char* EXPLANATION_ARG)
559fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
560ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!data) {
561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* start = p - U_PARSE_CONTEXT_LEN - 1;
565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (start < data) {
566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        start = data;
567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (UChar* x = p; --x >= start;) {
569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (!*x) {
570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = x+1;
571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            break;
572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const UChar* limit = p + U_PARSE_CONTEXT_LEN - 1;
575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (limit > e) {
576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        limit = e;
577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_strncpy(pe.preContext, start, (int32_t)(p-start));
579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.preContext[p-start] = 0;
580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    u_strncpy(pe.postContext, p, (int32_t)(limit-p));
581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.postContext[limit-p] = 0;
582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    pe.offset = (int32_t)(p - data);
583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
584f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius#ifdef RBNF_DEBUG
585fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    fprintf(stderr, "%s at or near character %ld: ", EXPLANATION_ARG, p-data);
586ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
587ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString msg;
588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append(start, p - start);
589ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append((UChar)0x002f); /* SOLIDUS/SLASH */
590ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    msg.append(p, limit-p);
591fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    msg.append(UNICODE_STRING_SIMPLE("'"));
592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    char buf[128];
594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = msg.extract(0, msg.length(), buf, 128);
595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len >= 128) {
596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf[127] = 0;
597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        buf[len] = 0;
599ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fprintf(stderr, "%s\n", buf);
601ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    fflush(stderr);
602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
604ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_free(data);
605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    data = NULL;
606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    p = NULL;
607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    e = NULL;
608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(ec)) {
610ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ec = U_PARSE_ERROR;
611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
613ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringLocalizationInfo)
615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo*
617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::create(const UnicodeString& info, UParseError& perror, UErrorCode& status) {
618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t len = info.length();
623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (len == 0) {
624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL; // no error;
625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UChar* p = (UChar*)uprv_malloc(len * sizeof(UChar));
628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!p) {
629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    info.extract(p, len, status);
633ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!U_FAILURE(status)) {
634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ZERO_ERROR; // clear warning about non-termination
635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocDataParser parser(perror, status);
638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return parser.parse(p, len);
639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::~StringLocalizationInfo() {
642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (UChar*** p = (UChar***)data; *p; ++p) {
643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // remaining data is simply pointer into our unicode string data.
644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (*p) uprv_free(*p);
645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (data) uprv_free(data);
647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (info) uprv_free(info);
648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getRuleSetName(int32_t index) const {
653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (index >= 0 && index < getNumberOfRuleSets()) {
654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[0][index];
655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
660ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getLocaleName(int32_t index) const {
661ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (index >= 0 && index < getNumberOfDisplayLocales()) {
662ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[index+1][0];
663ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
664ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
665ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
666ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
667ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruconst UChar*
668ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruStringLocalizationInfo::getDisplayName(int32_t localeIndex, int32_t ruleIndex) const {
669ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localeIndex >= 0 && localeIndex < getNumberOfDisplayLocales() &&
670ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleIndex >= 0 && ruleIndex < getNumberOfRuleSets()) {
671ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return data[localeIndex+1][ruleIndex+1];
672ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
673ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
674ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
675ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
676ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// ----------
677ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
678ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
679ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const UnicodeString& locs,
680ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
681ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
682103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
683103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
684ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
685ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
686ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
687ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
688c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
689c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
690ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
691ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
692ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
693ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
694fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
695fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
696fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
697fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
698ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
699ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
700ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, locinfo, perror, status);
701ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
702ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
703ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
704ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const UnicodeString& locs,
705ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             UParseError& perror, UErrorCode& status)
706ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
707103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
708103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(Locale::getDefault())
711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
713c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
714c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
715ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
719fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
720fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
721fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
722fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, locinfo, perror, status);
726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             LocalizationInfo* info,
730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
732103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
733103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
738c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
739c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
740ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
744fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
745fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
746fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
747fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  init(description, info, perror, status);
750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UParseError& perror,
754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode& status)
755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
756103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
757103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(Locale::getDefault())
760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
762c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
763c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
764ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
765ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
766ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
767ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
768fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
769fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
770fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
771fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    init(description, NULL, perror, status);
774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
776ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
777ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         const Locale& aLocale,
778ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UParseError& perror,
779ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                         UErrorCode& status)
780ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
781103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
782103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(aLocale)
785ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
786ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
787c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
788c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
789ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
790ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
791ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
792ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
793fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
794fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
795fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
796fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    init(description, NULL, perror, status);
799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : ruleSets(NULL)
803103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
804103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
806ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(alocale)
807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
809c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
810c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
811ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
814ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
815fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
816fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
817fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
818fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
82485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    const char* rules_tag = "RBNFRules";
825ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    const char* fmt_tag = "";
826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    switch (tag) {
827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break;
828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break;
829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    case URBNF_DURATION: fmt_tag = "DurationRules"; break;
83085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    case URBNF_NUMBERING_SYSTEM: fmt_tag = "NumberingSystemRules"; break;
831ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    default: status = U_ILLEGAL_ARGUMENT_ERROR; return;
832ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
833ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
834ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO: read localization info from resource
835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    LocalizationInfo* locinfo = NULL;
836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UResourceBundle* nfrb = ures_open(U_ICUDATA_RBNF, locale.getName(), &status);
838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status),
840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                     ures_getLocaleByType(nfrb, ULOC_ACTUAL_LOCALE, &status));
84185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
84285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UResourceBundle* rbnfRules = ures_getByKeyWithFallback(nfrb, rules_tag, NULL, &status);
84385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
84485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(nfrb);
84585bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
84685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UResourceBundle* ruleSets = ures_getByKeyWithFallback(rbnfRules, fmt_tag, NULL, &status);
84785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (U_FAILURE(status)) {
84885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(rbnfRules);
84985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ures_close(nfrb);
85085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
85185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
852103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
85385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        UnicodeString desc;
85485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        while (ures_hasNext(ruleSets)) {
855103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius           desc.append(ures_getNextUnicodeString(ruleSets,NULL,&status));
85685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
857ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UParseError perror;
85885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
859c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        init(desc, locinfo, perror, status);
86085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
86185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(ruleSets);
86285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        ures_close(rbnfRules);
863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ures_close(nfrb);
865ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
866ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
867ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  : NumberFormat(rhs)
869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , ruleSets(NULL)
870103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , ruleSetDescriptions(NULL)
871103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius  , numRuleSets(0)
872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , defaultRuleSet(NULL)
873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , locale(rhs.locale)
874ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , collator(NULL)
875ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , decimalFormatSymbols(NULL)
876c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultInfinityRule(NULL)
877c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert  , defaultNaNRule(NULL)
878ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert  , roundingMode(DecimalFormat::ERoundingMode::kRoundUnnecessary)
879ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenient(FALSE)
880ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , lenientParseRules(NULL)
881ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru  , localizations(NULL)
882fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationInfoSet(FALSE)
883fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForUIListMenu(FALSE)
884fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationForStandAlone(FALSE)
885fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius  , capitalizationBrkIter(NULL)
886ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
887ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->operator=(rhs);
888ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
889ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
890ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// --------
891ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
892ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat&
893ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs)
894ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
895fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (this == &rhs) {
896fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        return *this;
897fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
898fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    NumberFormat::operator=(rhs);
899ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UErrorCode status = U_ZERO_ERROR;
900ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dispose();
901ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    locale = rhs.locale;
902ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenient = rhs.lenient;
903ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
904ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UParseError perror;
905fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    setDecimalFormatSymbols(*rhs.getDecimalFormatSymbols());
906c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    init(rhs.originalDescription, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
907fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    setDefaultRuleSet(rhs.getDefaultRuleSetName(), status);
908ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    setRoundingMode(rhs.getRoundingMode());
909fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
910fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    capitalizationInfoSet = rhs.capitalizationInfoSet;
911fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    capitalizationForUIListMenu = rhs.capitalizationForUIListMenu;
912fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    capitalizationForStandAlone = rhs.capitalizationForStandAlone;
913fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_BREAK_ITERATION
914fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    capitalizationBrkIter = (rhs.capitalizationBrkIter!=NULL)? rhs.capitalizationBrkIter->clone(): NULL;
915fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
916ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
917ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return *this;
918ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
919ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
920ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::~RuleBasedNumberFormat()
921ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
922ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    dispose();
923ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
924ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
925ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruFormat*
926ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::clone(void) const
927ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
928fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return new RuleBasedNumberFormat(*this);
929ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
930ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
931ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUBool
932ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::operator==(const Format& other) const
933ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
934ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (this == &other) {
935ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return TRUE;
936ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
937ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
93827f654740f2a26ad62a5c155af9199af9e69b889claireho    if (typeid(*this) == typeid(other)) {
939ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        const RuleBasedNumberFormat& rhs = (const RuleBasedNumberFormat&)other;
940fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // test for capitalization info equality is adequately handled
941fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // by the NumberFormat test for fCapitalizationContext equality;
942fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // the info here is just derived from that.
943ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (locale == rhs.locale &&
944ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenient == rhs.lenient &&
945ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (localizations == NULL
946ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ? rhs.localizations == NULL
947ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                : (rhs.localizations == NULL
948ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    ? FALSE
949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    : *localizations == rhs.localizations))) {
950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet** p = ruleSets;
952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet** q = rhs.ruleSets;
953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (p == NULL) {
954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return q == NULL;
955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else if (q == NULL) {
956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return FALSE;
957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (*p && *q && (**p == **q)) {
959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++p;
960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++q;
961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            return *q == NULL && *p == NULL;
963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return FALSE;
967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRules() const
971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
972ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString result;
973ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets != NULL) {
974ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
975ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            (*p)->appendRules(result);
976ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
977ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
978ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
979ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
980ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
981ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
982ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetName(int32_t index) const
983ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
984ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
985c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
986c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return string;
987c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
988c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    else if (ruleSets) {
989ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString result;
990ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
991ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = *p;
992ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs->isPublic()) {
993ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (--index == -1) {
994ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    rs->getName(result);
995ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    return result;
996ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
997ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
998ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
999ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1000ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString empty;
1001ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return empty;
1002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
1005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getNumberOfRuleSetNames() const
1006ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1007ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int32_t result = 0;
1008ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
1009c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        result = localizations->getNumberOfRuleSets();
1010c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1011c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    else if (ruleSets) {
1012ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
1013ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((**p).isPublic()) {
1014ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++result;
1015ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1016ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1017ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1018ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return result;
1019ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1020ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1021ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruint32_t
1022ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getNumberOfRuleSetDisplayNameLocales(void) const {
1023ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
1024ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return localizations->getNumberOfDisplayLocales();
1025ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1026ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return 0;
1027ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1028ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1029ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruLocale
1030ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayNameLocale(int32_t index, UErrorCode& status) const {
1031ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1032ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return Locale("");
1033ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1034ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations && index >= 0 && index < localizations->getNumberOfDisplayLocales()) {
1035ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString name(TRUE, localizations->getLocaleName(index), -1);
1036ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char buffer[64];
1037ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t cap = name.length() + 1;
1038ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        char* bp = buffer;
1039ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (cap > 64) {
1040ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            bp = (char *)uprv_malloc(cap);
1041ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (bp == NULL) {
1042ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1043ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return Locale("");
1044ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1045ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1046ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        name.extract(0, name.length(), bp, cap, UnicodeString::kInvariant);
1047ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Locale retLocale(bp);
1048ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (bp != buffer) {
1049ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            uprv_free(bp);
1050ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1051ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return retLocale;
1052ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1053ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    status = U_ILLEGAL_ARGUMENT_ERROR;
1054ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Locale retLocale;
1055ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return retLocale;
1056ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1057ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1058ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
1059ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayName(int32_t index, const Locale& localeParam) {
1060ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations && index >= 0 && index < localizations->getNumberOfRuleSets()) {
1061ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString localeName(localeParam.getBaseName(), -1, UnicodeString::kInvariant);
1062ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t len = localeName.length();
1063ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UChar* localeStr = localeName.getBuffer(len + 1);
1064ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (len >= 0) {
1065ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            localeStr[len] = 0;
1066ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int32_t ix = localizations->indexForLocale(localeStr);
1067ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ix >= 0) {
1068ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString name(TRUE, localizations->getDisplayName(ix, index), -1);
1069ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return name;
1070ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1071ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1072ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // trim trailing portion, skipping over ommitted sections
1073ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            do { --len;} while (len > 0 && localeStr[len] != 0x005f); // underscore
1074ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            while (len > 0 && localeStr[len-1] == 0x005F) --len;
1075ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1076ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString name(TRUE, localizations->getRuleSetName(index), -1);
1077ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return name;
1078ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1079ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString bogus;
1080ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bogus.setToBogus();
1081ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return bogus;
1082ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1083ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1084ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
1085ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getRuleSetDisplayName(const UnicodeString& ruleSetName, const Locale& localeParam) {
1086ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizations) {
1087ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UnicodeString rsn(ruleSetName);
1088ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t ix = localizations->indexForRuleSet(rsn.getTerminatedBuffer());
1089ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return getRuleSetDisplayName(ix, localeParam);
1090ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1091ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString bogus;
1092ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    bogus.setToBogus();
1093ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return bogus;
1094ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1095ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1096ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruNFRuleSet*
1097ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status) const
1098ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1099ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status) && ruleSets) {
1100ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
1101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = *p;
1102ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs->isNamed(name)) {
1103ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return rs;
1104ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1105ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_ILLEGAL_ARGUMENT_ERROR;
1107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return NULL;
1109ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1110ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1111ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
11120596faeddefbf198de137d5e893708495ab1584cFredrik RoubertRuleBasedNumberFormat::format(const DigitList &number,
11130596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                      UnicodeString &appendTo,
11140596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                      FieldPositionIterator *posIter,
11150596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                      UErrorCode &status) const {
11160596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (U_FAILURE(status)) {
11170596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        return appendTo;
11180596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11190596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    DigitList copy(number);
11200596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (copy.fitsIntoInt64(false)) {
11210596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        format(((DigitList &)number).getInt64(), appendTo, posIter, status);
11220596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11230596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    else {
11240596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        copy.roundAtExponent(0);
11250596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (copy.fitsIntoInt64(false)) {
11260596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            format(number.getDouble(), appendTo, posIter, status);
11270596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
11280596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        else {
11290596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // We're outside of our normal range that this framework can handle.
11300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // The DecimalFormat will provide more accurate results.
11310596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
11320596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
11330596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
11340596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            Formattable f;
11350596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            f.adoptDigitList(new DigitList(number));
11360596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            decimalFormat->format(f, appendTo, posIter, status);
11370596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            delete decimalFormat;
11380596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
11390596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11400596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return appendTo;
11410596faeddefbf198de137d5e893708495ab1584cFredrik Roubert}
11420596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
11430596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
11440596faeddefbf198de137d5e893708495ab1584cFredrik RoubertUnicodeString&
11450596faeddefbf198de137d5e893708495ab1584cFredrik RoubertRuleBasedNumberFormat::format(const DigitList &number,
11460596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                     UnicodeString& appendTo,
11470596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                     FieldPosition& pos,
11480596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                     UErrorCode &status) const {
11490596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (U_FAILURE(status)) {
11500596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        return appendTo;
11510596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11520596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    DigitList copy(number);
11530596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (copy.fitsIntoInt64(false)) {
11540596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        format(((DigitList &)number).getInt64(), appendTo, pos, status);
11550596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11560596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    else {
11570596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        copy.roundAtExponent(0);
11580596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (copy.fitsIntoInt64(false)) {
11590596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            format(number.getDouble(), appendTo, pos, status);
11600596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
11610596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        else {
11620596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // We're outside of our normal range that this framework can handle.
11630596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // The DecimalFormat will provide more accurate results.
11640596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
11650596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
11660596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
11670596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            Formattable f;
11680596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            f.adoptDigitList(new DigitList(number));
11690596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            decimalFormat->format(f, appendTo, pos, status);
11700596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            delete decimalFormat;
11710596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
11720596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
11730596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return appendTo;
11740596faeddefbf198de137d5e893708495ab1584cFredrik Roubert}
11750596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
11760596faeddefbf198de137d5e893708495ab1584cFredrik RoubertUnicodeString&
1177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int32_t number,
1178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
11790596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                              FieldPosition& pos) const
1180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
11810596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return format((int64_t)number, toAppendTo, pos);
1182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int64_t number,
1187ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */) const
1189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (defaultRuleSet) {
1191f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius        UErrorCode status = U_ZERO_ERROR;
11920596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        format(number, defaultRuleSet, toAppendTo, status);
1193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1195ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(double number,
1200ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */) const
1202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
12030596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    UErrorCode status = U_ZERO_ERROR;
1204c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (defaultRuleSet) {
1205ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        format(number, *defaultRuleSet, toAppendTo, status);
1206b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho    }
1207ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    return toAppendTo;
1208ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1209ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1210ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1211ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1212ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int32_t number,
1213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
12150596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                              FieldPosition& pos,
1216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
12180596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
1219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(int64_t number,
1224ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1226ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */,
1227ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1229ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1230103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
1231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // throw new IllegalArgumentException("Can't use internal rule set");
1232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1233ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet *rs = findRuleSet(ruleSetName, status);
1235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs) {
12360596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                format(number, rs, toAppendTo, status);
1237ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1241ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString&
1245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::format(double number,
1246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              const UnicodeString& ruleSetName,
1247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UnicodeString& toAppendTo,
1248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              FieldPosition& /* pos */,
1249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                              UErrorCode& status) const
1250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1252103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
1253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // throw new IllegalArgumentException("Can't use internal rule set");
1254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet *rs = findRuleSet(ruleSetName, status);
1257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs) {
1258ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                format(number, *rs, toAppendTo, status);
1259ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1260ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1261ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1262ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return toAppendTo;
1263ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1264ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1265ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertvoid
1266ffdc27edd5503111189fc11165c5a11289a71f79Fredrik RoubertRuleBasedNumberFormat::format(double number,
1267ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                              NFRuleSet& rs,
1268ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                              UnicodeString& toAppendTo,
1269ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert                              UErrorCode& status) const
1270ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert{
1271ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    int32_t startPos = toAppendTo.length();
1272ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    if (getRoundingMode() != DecimalFormat::ERoundingMode::kRoundUnnecessary && !uprv_isNaN(number) && !uprv_isInfinite(number)) {
1273ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        DigitList digitList;
1274ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        digitList.set(number);
1275ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        digitList.setRoundingMode(getRoundingMode());
1276ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        digitList.roundFixedPoint(getMaximumFractionDigits());
1277ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert        number = digitList.getDouble();
1278ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    }
1279ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    rs.format(number, toAppendTo, toAppendTo.length(), 0, status);
1280ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    adjustForCapitalizationContext(startPos, toAppendTo, status);
1281ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert}
1282ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
12830596faeddefbf198de137d5e893708495ab1584cFredrik Roubert/**
12840596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * Bottleneck through which all the public format() methods
12850596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * that take a long pass. By the time we get here, we know
12860596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * which rule set we're using to do the formatting.
12870596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * @param number The number to format
12880596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * @param ruleSet The rule set to use to format the number
12890596faeddefbf198de137d5e893708495ab1584cFredrik Roubert * @return The text that resulted from formatting the number
12900596faeddefbf198de137d5e893708495ab1584cFredrik Roubert */
12910596faeddefbf198de137d5e893708495ab1584cFredrik RoubertUnicodeString&
12920596faeddefbf198de137d5e893708495ab1584cFredrik RoubertRuleBasedNumberFormat::format(int64_t number, NFRuleSet *ruleSet, UnicodeString& toAppendTo, UErrorCode& status) const
12930596faeddefbf198de137d5e893708495ab1584cFredrik Roubert{
12940596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // all API format() routines that take a double vector through
12950596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // here.  We have these two identical functions-- one taking a
12960596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // double and one taking a long-- the couple digits of precision
12970596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // that long has but double doesn't (both types are 8 bytes long,
12980596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // but double has to borrow some of the mantissa bits to hold
12990596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // the exponent).
13000596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // Create an empty string buffer where the result will
13010596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // be built, and pass it to the rule set (along with an insertion
13020596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // position of 0 and the number being formatted) to the rule set
13030596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    // for formatting
13040596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
13050596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (U_SUCCESS(status)) {
13060596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (number == U_INT64_MIN) {
13070596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // We can't handle this value right now. Provide an accurate default value.
13080596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
13090596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            // TODO this section should probably be optimized. The DecimalFormat is shared in ICU4J.
13100596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            NumberFormat *decimalFormat = NumberFormat::createInstance(locale, UNUM_DECIMAL, status);
13110596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            Formattable f;
13120596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            FieldPosition pos(FieldPosition::DONT_CARE);
13130596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            DigitList *digitList = new DigitList();
13140596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            digitList->set(number);
13150596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            f.adoptDigitList(digitList);
13160596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            decimalFormat->format(f, toAppendTo, pos, status);
13170596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            delete decimalFormat;
13180596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
13190596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        else {
13200596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            int32_t startPos = toAppendTo.length();
13210596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            ruleSet->format(number, toAppendTo, toAppendTo.length(), 0, status);
13220596faeddefbf198de137d5e893708495ab1584cFredrik Roubert            adjustForCapitalizationContext(startPos, toAppendTo, status);
13230596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        }
13240596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    }
13250596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    return toAppendTo;
13260596faeddefbf198de137d5e893708495ab1584cFredrik Roubert}
13270596faeddefbf198de137d5e893708495ab1584cFredrik Roubert
1328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString&
1329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusRuleBasedNumberFormat::adjustForCapitalizationContext(int32_t startPos,
13300596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                                                      UnicodeString& currentResult,
13310596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                                                      UErrorCode& status) const
1332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
1333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_BREAK_ITERATION
13340596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    UDisplayContext capitalizationContext = getContext(UDISPCTX_TYPE_CAPITALIZATION, status);
13350596faeddefbf198de137d5e893708495ab1584cFredrik Roubert    if (capitalizationContext != UDISPCTX_CAPITALIZATION_NONE && startPos == 0 && currentResult.length() > 0) {
1336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        // capitalize currentResult according to context
1337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        UChar32 ch = currentResult.char32At(0);
13380596faeddefbf198de137d5e893708495ab1584cFredrik Roubert        if (u_islower(ch) && U_SUCCESS(status) && capitalizationBrkIter != NULL &&
13390596faeddefbf198de137d5e893708495ab1584cFredrik Roubert              ( capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
13400596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) ||
13410596faeddefbf198de137d5e893708495ab1584cFredrik Roubert                (capitalizationContext == UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
1342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // titlecase first word of currentResult, here use sentence iterator unlike current implementations
1343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            // in LocaleDisplayNamesImpl::adjustForUsageAndContext and RelativeDateFormat::format
1344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            currentResult.toTitle(capitalizationBrkIter, locale, U_TITLECASE_NO_LOWERCASE | U_TITLECASE_NO_BREAK_ADJUSTMENT);
1345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    return currentResult;
1349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1352ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1353ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::parse(const UnicodeString& text,
1354ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             Formattable& result,
1355ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                             ParsePosition& parsePosition) const
1356ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1357ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1358ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePosition.setErrorIndex(0);
1359ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1360ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1361ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1362ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString workingText(text, parsePosition.getIndex());
1363ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition workingPos(0);
1364ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1365ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ParsePosition high_pp(0);
1366ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    Formattable high_result;
1367ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1368ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (NFRuleSet** p = ruleSets; *p; ++p) {
1369ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        NFRuleSet *rp = *p;
137085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if (rp->isPublic() && rp->isParseable()) {
1371ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ParsePosition working_pp(0);
1372ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            Formattable working_result;
1373ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1374ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            rp->parse(workingText, working_pp, kMaxDouble, working_result);
1375ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (working_pp.getIndex() > high_pp.getIndex()) {
1376ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                high_pp = working_pp;
1377ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                high_result = working_result;
1378ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1379ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                if (high_pp.getIndex() == workingText.length()) {
1380ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                    break;
1381ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                }
1382ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1383ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1384ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1385ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
138685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    int32_t startIndex = parsePosition.getIndex();
138785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    parsePosition.setIndex(startIndex + high_pp.getIndex());
1388ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (high_pp.getIndex() > 0) {
1389ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        parsePosition.setErrorIndex(-1);
139085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho    } else {
139185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        int32_t errorIndex = (high_pp.getErrorIndex()>0)? high_pp.getErrorIndex(): 0;
139285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        parsePosition.setErrorIndex(startIndex + errorIndex);
1393ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1394ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    result = high_result;
1395ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (result.getType() == Formattable::kDouble) {
13968de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        double d = result.getDouble();
13978de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert        if (!uprv_isNaN(d) && d == uprv_trunc(d) && INT32_MIN <= d && d <= INT32_MAX) {
13988de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            // Note: casting a double to an int when the double is too large or small
13998de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            //       to fit the destination is undefined behavior. The explicit range checks,
14008de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            //       above, are required. Just casting and checking the result value is undefined.
14018de051c3d18a56cc126f0f44e368495a52f9148cFredrik Roubert            result.setLong(static_cast<int32_t>(d));
1402ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1403ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1404ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1405ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1406ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1407ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1408ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1409ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::setLenient(UBool enabled)
1410ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1411ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenient = enabled;
1412ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!enabled && collator) {
1413ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete collator;
1414ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        collator = NULL;
1415ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1416ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1417ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1418ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1419ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1420ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1421ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::setDefaultRuleSet(const UnicodeString& ruleSetName, UErrorCode& status) {
1422ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_SUCCESS(status)) {
1423ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSetName.isEmpty()) {
1424ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          if (localizations) {
1425ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              UnicodeString name(TRUE, localizations->getRuleSetName(0), -1);
1426ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru              defaultRuleSet = findRuleSet(name, status);
1427ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          } else {
1428ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            initDefaultRuleSet();
1429ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru          }
1430ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else if (ruleSetName.startsWith(UNICODE_STRING_SIMPLE("%%"))) {
1431ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_ILLEGAL_ARGUMENT_ERROR;
1432ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        } else {
1433ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* result = findRuleSet(ruleSetName, status);
1434ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (result != NULL) {
1435ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = result;
1436ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1437ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1438ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1439ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1440ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1441ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruUnicodeString
1442ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getDefaultRuleSetName() const {
1443c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    UnicodeString result;
1444c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (defaultRuleSet && defaultRuleSet->isPublic()) {
1445c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        defaultRuleSet->getName(result);
1446c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    } else {
1447c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        result.setToBogus();
1448c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1449c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return result;
1450ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1451ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1452ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1453ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::initDefaultRuleSet()
1454ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1455ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    defaultRuleSet = NULL;
1456ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1457c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
1458ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1459ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1460c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    const UnicodeString spellout(UNICODE_STRING_SIMPLE("%spellout-numbering"));
1461c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    const UnicodeString ordinal(UNICODE_STRING_SIMPLE("%digits-ordinal"));
1462c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    const UnicodeString duration(UNICODE_STRING_SIMPLE("%duration"));
146385bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho
1464ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    NFRuleSet**p = &ruleSets[0];
1465ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (*p) {
146685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        if ((*p)->isNamed(spellout) || (*p)->isNamed(ordinal) || (*p)->isNamed(duration)) {
146785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            defaultRuleSet = *p;
146885bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            return;
146985bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        } else {
147085bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho            ++p;
147185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        }
1472ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1473ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1474ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    defaultRuleSet = *--p;
1475ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!defaultRuleSet->isPublic()) {
1476ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (p != ruleSets) {
1477ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if ((*--p)->isPublic()) {
1478ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = *p;
1479ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break;
1480ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1481ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1482ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1483ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1484ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1485ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1486ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1487ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* localizationInfos,
1488ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                            UParseError& pErr, UErrorCode& status)
1489ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1490ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // TODO: implement UParseError
1491ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    uprv_memset(&pErr, 0, sizeof(UParseError));
1492ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Note: this can leave ruleSets == NULL, so remaining code should check
1493ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (U_FAILURE(status)) {
1494ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1495ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1496ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1497c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    initializeDecimalFormatSymbols(status);
1498c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    initializeDefaultInfinityRule(status);
1499c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    initializeDefaultNaNRule(status);
1500c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (U_FAILURE(status)) {
1501c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return;
1502c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1503c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1504ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    this->localizations = localizationInfos == NULL ? NULL : localizationInfos->ref();
1505ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1506ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString description(rules);
1507ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!description.length()) {
1508ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1509ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1510ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1511ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1512ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // start by stripping the trailing whitespace from all the rules
1513ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // (this is all the whitespace follwing each semicolon in the
1514ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // description).  This allows us to look for rule-set boundaries
1515ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // by searching for ";%" without having to worry about whitespace
1516ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // between the ; and the %
1517ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    stripWhitespace(description);
1518ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1519ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // check to see if there's a set of lenient-parse rules.  If there
1520ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is, pull them out into our temporary holding place for them,
1521ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and delete them from the description before the real desciption-
1522ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // parsing code sees them
1523103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    int32_t lp = description.indexOf(gLenientParse, -1, 0);
1524ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (lp != -1) {
1525ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we've got to make sure we're not in the middle of a rule
1526ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // (where "%%lenient-parse" would actually get treated as
1527ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rule text)
1528ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (lp == 0 || description.charAt(lp - 1) == gSemiColon) {
1529ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // locate the beginning and end of the actual collation
1530ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // rules (there may be whitespace between the name and
1531ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the first token in the description)
1532103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            int lpEnd = description.indexOf(gSemiPercent, 2, lp);
1533ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1534ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lpEnd == -1) {
1535ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                lpEnd = description.length() - 1;
1536ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1537ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            int lpStart = lp + u_strlen(gLenientParse);
1538b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            while (PatternProps::isWhiteSpace(description.charAt(lpStart))) {
1539ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ++lpStart;
1540ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1541ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1542ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // copy out the lenient-parse rules and delete them
1543ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // from the description
1544ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenientParseRules = new UnicodeString();
1545ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            /* test for NULL */
1546ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lenientParseRules == 0) {
1547ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1548ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                return;
1549ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1550ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            lenientParseRules->setTo(description, lpStart, lpEnd - lpStart);
1551ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1552ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            description.remove(lp, lpEnd + 1 - lp);
1553ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1554ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1555ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1556ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // pre-flight parsing the description and count the number of
1557ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // rule sets (";%" marks the end of one rule set and the beginning
1558ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // of the next)
1559103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    numRuleSets = 0;
1560103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, p)) {
1561ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++numRuleSets;
1562ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ++p;
1563ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1564ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ++numRuleSets;
1565ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1566ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // our rule list is an array of the appropriate size
1567ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    ruleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *));
1568ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    /* test for NULL */
1569ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets == 0) {
1570ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1571ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1572ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1573ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1574ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    for (int i = 0; i <= numRuleSets; ++i) {
1575ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSets[i] = NULL;
1576ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1577ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1578ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // divide up the descriptions into individual rule-set descriptions
1579ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and store them in a temporary array.  At each step, we also
1580ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // new up a rule set, but all this does is initialize its name
1581ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // and remove it from its description.  We can't actually parse
1582ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // the rest of the descriptions and finish initializing everything
1583ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // because we have to know the names and locations of all the rule
1584ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // sets before we can actually set everything up
1585ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if(!numRuleSets) {
158685bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        status = U_ILLEGAL_ARGUMENT_ERROR;
158785bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho        return;
1588ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1589103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1590103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    ruleSetDescriptions = new UnicodeString[numRuleSets];
1591ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSetDescriptions == 0) {
1592ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        status = U_MEMORY_ALLOCATION_ERROR;
1593ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return;
1594ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1595ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1596ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1597ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int curRuleSet = 0;
1598ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t start = 0;
1599103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) {
1600ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
1601c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
1602ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (ruleSets[curRuleSet] == 0) {
1603ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                status = U_MEMORY_ALLOCATION_ERROR;
1604103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius                return;
1605ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1606ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++curRuleSet;
1607ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = p + 1;
1608ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1609ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start);
1610c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        ruleSets[curRuleSet] = new NFRuleSet(this, ruleSetDescriptions, curRuleSet, status);
1611ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (ruleSets[curRuleSet] == 0) {
1612ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            status = U_MEMORY_ALLOCATION_ERROR;
1613103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius            return;
1614ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1615ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1616ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1617ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // now we can take note of the formatter's default rule set, which
1618ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is the last public rule set in the description (it's the last
1619ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // rather than the first so that a user can create a new formatter
1620ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // from an existing formatter and change its default behavior just
1621ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // by appending more rule sets to the end)
1622ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1623ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // {dlf} Initialization of a fraction rule set requires the default rule
1624ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set to be known.  For purposes of initialization, this is always the
1625ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // last public rule set, no matter what the localization data says.
1626ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    initDefaultRuleSet();
1627ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1628ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // finally, we can go back through the temporary descriptions
1629ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // list and finish seting up the substructure (and we throw
1630ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // away the temporary descriptions as we go)
1631ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    {
1632ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int i = 0; i < numRuleSets; i++) {
1633c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            ruleSets[i]->parseRules(ruleSetDescriptions[i], status);
1634ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1635ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1636ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1637ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // Now that the rules are initialized, the 'real' default rule
1638ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // set can be adjusted by the localization data.
1639ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1640ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // The C code keeps the localization array as is, rather than building
1641ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // a separate array of the public rule set names, so we have less work
1642ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // to do here-- but we still need to check the names.
1643ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1644ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (localizationInfos) {
1645ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // confirm the names, if any aren't in the rules, that's an error
1646ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // it is ok if the rules contain public rule sets that are not in this list
1647ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (int32_t i = 0; i < localizationInfos->getNumberOfRuleSets(); ++i) {
1648ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            UnicodeString name(TRUE, localizationInfos->getRuleSetName(i), -1);
1649ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            NFRuleSet* rs = findRuleSet(name, status);
1650ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (rs == NULL) {
1651ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                break; // error
1652ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1653ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (i == 0) {
1654ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                defaultRuleSet = rs;
1655ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1656ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1657ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    } else {
1658ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        defaultRuleSet = getDefaultRuleSet();
1659ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1660fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    originalDescription = rules;
1661fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1662fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1663fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// override the NumberFormat implementation in order to
1664fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// lazily initialize relevant items
1665fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
1666fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusRuleBasedNumberFormat::setContext(UDisplayContext value, UErrorCode& status)
1667fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
1668fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    NumberFormat::setContext(value, status);
1669fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_SUCCESS(status)) {
1670fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    	if (!capitalizationInfoSet &&
1671fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    	        (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU || value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE)) {
1672fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    	    initCapitalizationContextInfo(locale);
1673fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    	    capitalizationInfoSet = TRUE;
1674fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1675fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_BREAK_ITERATION
1676fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if ( capitalizationBrkIter == NULL && (value==UDISPCTX_CAPITALIZATION_FOR_BEGINNING_OF_SENTENCE ||
1677fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (value==UDISPCTX_CAPITALIZATION_FOR_UI_LIST_OR_MENU && capitalizationForUIListMenu) ||
1678fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                (value==UDISPCTX_CAPITALIZATION_FOR_STANDALONE && capitalizationForStandAlone)) ) {
1679fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            UErrorCode status = U_ZERO_ERROR;
1680fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            capitalizationBrkIter = BreakIterator::createSentenceInstance(locale, status);
1681fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            if (U_FAILURE(status)) {
1682fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                delete capitalizationBrkIter;
1683fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                capitalizationBrkIter = NULL;
1684fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            }
1685fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1686fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1687fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1688fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}
1689fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1690fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid
1691fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusRuleBasedNumberFormat::initCapitalizationContextInfo(const Locale& thelocale)
1692fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius{
1693fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_BREAK_ITERATION
1694fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    const char * localeID = (thelocale != NULL)? thelocale.getBaseName(): NULL;
1695fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UErrorCode status = U_ZERO_ERROR;
1696fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    UResourceBundle *rb = ures_open(NULL, localeID, &status);
1697fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    rb = ures_getByKeyWithFallback(rb, "contextTransforms", rb, &status);
1698fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    rb = ures_getByKeyWithFallback(rb, "number-spellout", rb, &status);
1699fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    if (U_SUCCESS(status) && rb != NULL) {
1700fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        int32_t len = 0;
1701fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        const int32_t * intVector = ures_getIntVector(rb, &len, &status);
1702fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        if (U_SUCCESS(status) && intVector != NULL && len >= 2) {
1703fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            capitalizationForUIListMenu = intVector[0];
1704fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius            capitalizationForStandAlone = intVector[1];
1705fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius        }
1706fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    }
1707fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    ures_close(rb);
1708fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1709ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1710ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1711ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1712ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::stripWhitespace(UnicodeString& description)
1713ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1714ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // iterate through the characters...
1715ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    UnicodeString result;
1716ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1717ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    int start = 0;
1718ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    while (start != -1 && start < description.length()) {
1719ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // seek to the first non-whitespace character...
1720ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        while (start < description.length()
1721b26ce3a7367e4ed2ee7ddddcdc3f3d3377a455c2claireho            && PatternProps::isWhiteSpace(description.charAt(start))) {
1722ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            ++start;
1723ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1724ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1725ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // locate the next semicolon in the text and copy the text from
1726ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // our current position up to that semicolon into the result
1727ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        int32_t p = description.indexOf(gSemiColon, start);
1728ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (p == -1) {
1729ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // or if we don't find a semicolon, just copy the rest of
1730ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            // the string into the result
1731ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.append(description, start, description.length() - start);
1732ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = -1;
1733ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1734ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else if (p < description.length()) {
1735ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            result.append(description, start, p + 1 - start);
1736ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = p + 1;
1737ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1738ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1739ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // when we get here, we've seeked off the end of the sring, and
1740ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // we terminate the loop (we continue until *start* is -1 rather
1741ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // than until *p* is -1, because otherwise we'd miss the last
1742ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rule in the description)
1743ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        else {
1744ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            start = -1;
1745ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1746ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1747ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1748ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    description.setTo(result);
1749ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1750ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1751ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1752ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queruvoid
1753ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::dispose()
1754ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1755ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (ruleSets) {
1756ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        for (NFRuleSet** p = ruleSets; *p; ++p) {
1757ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete *p;
1758ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1759ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        uprv_free(ruleSets);
1760ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        ruleSets = NULL;
1761ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1762ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1763103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (ruleSetDescriptions) {
1764103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        delete [] ruleSetDescriptions;
1765c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        ruleSetDescriptions = NULL;
1766103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1767103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1768ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1769ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete collator;
1770ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1771ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    collator = NULL;
1772ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1773ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete decimalFormatSymbols;
1774ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    decimalFormatSymbols = NULL;
1775ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1776c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete defaultInfinityRule;
1777c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    defaultInfinityRule = NULL;
1778c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1779c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete defaultNaNRule;
1780c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    defaultNaNRule = NULL;
1781c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1782ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    delete lenientParseRules;
1783ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    lenientParseRules = NULL;
1784ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1785fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#if !UCONFIG_NO_BREAK_ITERATION
1786c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    delete capitalizationBrkIter;
1787c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    capitalizationBrkIter = NULL;
1788fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#endif
1789fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius
1790c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (localizations) {
1791c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        localizations = localizations->unref();
1792c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1793ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1794ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1795ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1796ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//-----------------------------------------------------------------------
1797ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// package-internal API
1798ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru//-----------------------------------------------------------------------
1799ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1800ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/**
1801ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Returns the collator to use for lenient parsing.  The collator is lazily created:
1802ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * this function creates it the first time it's called.
1803ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @return The collator to use for lenient parsing, or null if lenient parsing
1804ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * is turned off.
1805ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/
1806fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst RuleBasedCollator*
1807ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruRuleBasedNumberFormat::getCollator() const
1808ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1809ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_COLLATION
1810ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (!ruleSets) {
1811ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        return NULL;
1812ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1813ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1814fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius    // lazy-evaluate the collator
1815ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (collator == NULL && lenient) {
1816ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // create a default collator based on the formatter's locale,
1817ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // then pull out that collator's rules, append any additional
1818ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // rules specified in the description, and create a _new_
1819ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        // collator based on the combinaiton of those rules
1820ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1821ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        UErrorCode status = U_ZERO_ERROR;
1822ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1823ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        Collator* temp = Collator::createInstance(locale, status);
182427f654740f2a26ad62a5c155af9199af9e69b889claireho        RuleBasedCollator* newCollator;
182527f654740f2a26ad62a5c155af9199af9e69b889claireho        if (U_SUCCESS(status) && (newCollator = dynamic_cast<RuleBasedCollator*>(temp)) != NULL) {
1826ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (lenientParseRules) {
1827ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                UnicodeString rules(newCollator->getRules());
1828ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                rules.append(*lenientParseRules);
1829ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1830ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                newCollator = new RuleBasedCollator(rules, status);
183185bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                // Exit if newCollator could not be created.
183285bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                if (newCollator == NULL) {
1833fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius                    return NULL;
183485bf2e2fbc60a9f938064abc8127d61da7d19882Claire Ho                }
1835ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1836ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                temp = NULL;
1837ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1838ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            if (U_SUCCESS(status)) {
1839ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                newCollator->setAttribute(UCOL_DECOMPOSITION_MODE, UCOL_ON, status);
1840ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                // cast away const
1841ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                ((RuleBasedNumberFormat*)this)->collator = newCollator;
1842ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            } else {
1843ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru                delete newCollator;
1844ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            }
1845ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1846ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        delete temp;
1847ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1848ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
1849ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1850ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // if lenient-parse mode is off, this will be null
1851ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // (see setLenientParseMode())
1852ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return collator;
1853ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1854ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1855ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1856ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruDecimalFormatSymbols*
1857c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::initializeDecimalFormatSymbols(UErrorCode &status)
1858ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{
1859ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // lazy-evaluate the DecimalFormatSymbols object.  This object
1860ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // is shared by all DecimalFormat instances belonging to this
1861ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    // formatter
1862ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    if (decimalFormatSymbols == NULL) {
1863ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status);
1864ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        if (U_SUCCESS(status)) {
1865c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            decimalFormatSymbols = temp;
1866c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1867c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else {
1868ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru            delete temp;
1869ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru        }
1870ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    }
1871ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru    return decimalFormatSymbols;
1872ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}
1873ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
1874c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert/**
1875c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
1876c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert * instances owned by this formatter.
1877c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert*/
1878c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertconst DecimalFormatSymbols*
1879c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::getDecimalFormatSymbols() const
1880c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert{
1881c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return decimalFormatSymbols;
1882c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1883c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1884c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertNFRule*
1885c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::initializeDefaultInfinityRule(UErrorCode &status)
1886c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert{
1887c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (U_FAILURE(status)) {
1888c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return NULL;
1889c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1890c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (defaultInfinityRule == NULL) {
1891c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        UnicodeString rule(UNICODE_STRING_SIMPLE("Inf: "));
1892c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kInfinitySymbol));
1893c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        NFRule* temp = new NFRule(this, rule, status);
1894c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (U_SUCCESS(status)) {
1895c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            defaultInfinityRule = temp;
1896c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1897c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else {
1898c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            delete temp;
1899c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1900c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1901c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return defaultInfinityRule;
1902c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1903c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1904c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertconst NFRule*
1905c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::getDefaultInfinityRule() const
1906c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert{
1907c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return defaultInfinityRule;
1908c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1909c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1910c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertNFRule*
1911c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::initializeDefaultNaNRule(UErrorCode &status)
1912c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert{
1913c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (U_FAILURE(status)) {
1914c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        return NULL;
1915c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1916c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    if (defaultNaNRule == NULL) {
1917c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        UnicodeString rule(UNICODE_STRING_SIMPLE("NaN: "));
1918c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        rule.append(getDecimalFormatSymbols()->getSymbol(DecimalFormatSymbols::kNaNSymbol));
1919c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        NFRule* temp = new NFRule(this, rule, status);
1920c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (U_SUCCESS(status)) {
1921c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            defaultNaNRule = temp;
1922c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1923c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        else {
1924c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            delete temp;
1925c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        }
1926c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    }
1927c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return defaultNaNRule;
1928c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1929c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1930c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubertconst NFRule*
1931c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik RoubertRuleBasedNumberFormat::getDefaultNaNRule() const
1932c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert{
1933c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert    return defaultNaNRule;
1934c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert}
1935c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1936103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// De-owning the current localized symbols and adopt the new symbols.
1937103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusvoid
1938103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusRuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
1939103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
1940103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (symbolsToAdopt == NULL) {
1941103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        return; // do not allow caller to set decimalFormatSymbols to NULL
1942103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1943103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1944103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    if (decimalFormatSymbols != NULL) {
1945103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        delete decimalFormatSymbols;
1946103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1947103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1948103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    decimalFormatSymbols = symbolsToAdopt;
1949103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1950103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    {
1951103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        // Apply the new decimalFormatSymbols by reparsing the rulesets
1952103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        UErrorCode status = U_ZERO_ERROR;
1953103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1954c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete defaultInfinityRule;
1955c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        defaultInfinityRule = NULL;
1956c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        initializeDefaultInfinityRule(status); // Reset with the new DecimalFormatSymbols
1957c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1958c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        delete defaultNaNRule;
1959c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        defaultNaNRule = NULL;
1960c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        initializeDefaultNaNRule(status); // Reset with the new DecimalFormatSymbols
1961c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert
1962c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert        if (ruleSets) {
1963c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            for (int32_t i = 0; i < numRuleSets; i++) {
1964c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert                ruleSets[i]->setDecimalFormatSymbols(*symbolsToAdopt, status);
1965c14898b482f76ecab9026615e2e4c6fe78358bdcFredrik Roubert            }
1966103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius        }
1967103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    }
1968103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1969103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1970103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius// Setting the symbols is equlivalent to adopting a newly created localized symbols.
1971103e9ffba2cba345d0078eb8b8db33249f81840aCraig Corneliusvoid
1972103e9ffba2cba345d0078eb8b8db33249f81840aCraig CorneliusRuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
1973103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius{
1974103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius    adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
1975103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius}
1976103e9ffba2cba345d0078eb8b8db33249f81840aCraig Cornelius
1977f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusPluralFormat *
1978f9878a236aa0d9662d8e40cafdaf2e04cd615835ccorneliusRuleBasedNumberFormat::createPluralFormat(UPluralType pluralType,
1979f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                                          const UnicodeString &pattern,
1980f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius                                          UErrorCode& status) const
1981f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius{
1982f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius    return new PluralFormat(locale, pluralType, pattern, status);
1983f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius}
1984f9878a236aa0d9662d8e40cafdaf2e04cd615835ccornelius
1985ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert/**
1986ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * Get the rounding mode.
1987ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * @return A rounding mode
1988ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert */
1989ffdc27edd5503111189fc11165c5a11289a71f79Fredrik RoubertDecimalFormat::ERoundingMode RuleBasedNumberFormat::getRoundingMode() const {
1990ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    return roundingMode;
1991ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert}
1992ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
1993ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert/**
1994ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * Set the rounding mode.  This has no effect unless the rounding
1995ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * increment is greater than zero.
1996ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert * @param roundingMode A rounding mode
1997ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert */
1998ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubertvoid RuleBasedNumberFormat::setRoundingMode(DecimalFormat::ERoundingMode roundingMode) {
1999ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert    this->roundingMode = roundingMode;
2000ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert}
2001ffdc27edd5503111189fc11165c5a11289a71f79Fredrik Roubert
2002ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END
2003ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru
2004ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* U_HAVE_RBNF */
2005ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif
2006