16f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
26f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
36f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* Copyright (C) 1997-2013, International Business Machines Corporation
46f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org* and others. All Rights Reserved.
56f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*******************************************************************************
66f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
76f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
86f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "utypeinfo.h"  // for 'typeid' to work
96f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/rbnf.h"
116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if U_HAVE_RBNF
136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/normlzr.h"
156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/tblcoll.h"
166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uchar.h"
176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ucol.h"
186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/uloc.h"
196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/unum.h"
206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ures.h"
216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/ustring.h"
226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/utf16.h"
236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "unicode/udata.h"
246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "nfrs.h"
256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cmemory.h"
276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "cstring.h"
286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "patternprops.h"
296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "uresimp.h"
306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// debugging
326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// #define DEBUG
336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#ifdef DEBUG
356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#include "stdio.h"
366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define U_ICUDATA_RBNF U_ICUDATA_NAME U_TREE_SEPARATOR_STRING "rbnf"
396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar gPercentPercent[] =
416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x25, 0x25, 0
436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}; /* "%%" */
446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// All urbnf objects are created through openRules, so we init all of the
466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Unicode string constants required by rbnf, nfrs, or nfr here.
476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar gLenientParse[] =
486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x25, 0x25, 0x6C, 0x65, 0x6E, 0x69, 0x65, 0x6E, 0x74, 0x2D, 0x70, 0x61, 0x72, 0x73, 0x65, 0x3A, 0
506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}; /* "%%lenient-parse:" */
516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar gSemiColon = 0x003B;
526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar gSemiPercent[] =
536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    0x3B, 0x25, 0
556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}; /* ";%" */
566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define kSomeNumberOfBitsDiv2 22
586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define kHalfMaxDouble (double)(1 << kSomeNumberOfBitsDiv2)
596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define kMaxDouble (kHalfMaxDouble * kHalfMaxDouble)
606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_BEGIN
626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUOBJECT_DEFINE_RTTI_IMPLEMENTATION(RuleBasedNumberFormat)
646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/*
666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgThis is a utility class. It does not use ICU's RTTI.
676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgIf ICU's RTTI is needed again, you can uncomment the RTTI code and derive from UObject.
686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgPlease make sure that intltest passes on Windows in Release mode,
696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgsince the string pooling per compilation unit will mess up how RTTI works.
706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgThe RTTI code was also removed due to lack of code coverage.
716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass LocalizationInfo : public UMemory {
736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgprotected:
746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual ~LocalizationInfo();
756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uint32_t refcount;
766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic:
786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocalizationInfo() : refcount(0) {}
796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocalizationInfo* ref(void) {
816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++refcount;
826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return this;
836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocalizationInfo* unref(void) {
866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (refcount && --refcount == 0) {
876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete this;
886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual UBool operator==(const LocalizationInfo* rhs) const;
936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    inline  UBool operator!=(const LocalizationInfo* rhs) const { return !operator==(rhs); }
946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t getNumberOfRuleSets(void) const = 0;
966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getRuleSetName(int32_t index) const = 0;
976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t getNumberOfDisplayLocales(void) const = 0;
986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getLocaleName(int32_t index) const = 0;
996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const = 0;
1006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t indexForLocale(const UChar* locale) const;
1026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t indexForRuleSet(const UChar* ruleset) const;
1036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//    virtual UClassID getDynamicClassID() const = 0;
1056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//    static UClassID getStaticClassID(void);
1066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
1076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocalizationInfo::~LocalizationInfo() {}
1096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//UOBJECT_DEFINE_ABSTRACT_RTTI_IMPLEMENTATION(LocalizationInfo)
1116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// if both strings are NULL, this returns TRUE
1136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic UBool
1146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstreq(const UChar* lhs, const UChar* rhs) {
1156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (rhs == lhs) {
1166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
1176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (lhs && rhs) {
1196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return u_strcmp(lhs, rhs) == 0;
1206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
1226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
1256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocalizationInfo::operator==(const LocalizationInfo* rhs) const {
1266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (rhs) {
1276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (this == rhs) {
1286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return TRUE;
1296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t rsc = getNumberOfRuleSets();
1326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (rsc == rhs->getNumberOfRuleSets()) {
1336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for (int i = 0; i < rsc; ++i) {
1346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (!streq(getRuleSetName(i), rhs->getRuleSetName(i))) {
1356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return FALSE;
1366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
1376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t dlc = getNumberOfDisplayLocales();
1396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (dlc == rhs->getNumberOfDisplayLocales()) {
1406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                for (int i = 0; i < dlc; ++i) {
1416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    const UChar* locale = getLocaleName(i);
1426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    int32_t ix = rhs->indexForLocale(locale);
1436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // if no locale, ix is -1, getLocaleName returns null, so streq returns false
1446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    if (!streq(locale, rhs->getLocaleName(ix))) {
1456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        return FALSE;
1466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
1476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    for (int j = 0; j < rsc; ++j) {
1486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        if (!streq(getDisplayName(i, j), rhs->getDisplayName(ix, j))) {
1496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            return FALSE;
1506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                        }
1516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    }
1526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
1536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return TRUE;
1546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
1586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
1616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocalizationInfo::indexForLocale(const UChar* locale) const {
1626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (int i = 0; i < getNumberOfDisplayLocales(); ++i) {
1636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (streq(locale, getLocaleName(i))) {
1646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return i;
1656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return -1;
1686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
1716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocalizationInfo::indexForRuleSet(const UChar* ruleset) const {
1726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleset) {
1736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (int i = 0; i < getNumberOfRuleSets(); ++i) {
1746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (streq(ruleset, getRuleSetName(i))) {
1756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return i;
1766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
1776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
1786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
1796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return -1;
1806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
1816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgtypedef void (*Fn_Deleter)(void*);
1846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass VArray {
1866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void** buf;
1876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t cap;
1886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t size;
1896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Fn_Deleter deleter;
1906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic:
1916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    VArray() : buf(NULL), cap(0), size(0), deleter(NULL) {}
1926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    VArray(Fn_Deleter del) : buf(NULL), cap(0), size(0), deleter(del) {}
1946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
1956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ~VArray() {
1966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (deleter) {
1976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            for (int i = 0; i < size; ++i) {
1986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                (*deleter)(buf[i]);
1996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(buf);
2026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t length() {
2056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return size;
2066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void add(void* elem, UErrorCode& status) {
2096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(status)) {
2106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (size == cap) {
2116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (cap == 0) {
2126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cap = 1;
2136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else if (cap < 256) {
2146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cap *= 2;
2156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
2166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    cap += 256;
2176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (buf == NULL) {
2196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    buf = (void**)uprv_malloc(cap * sizeof(void*));
2206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                } else {
2216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    buf = (void**)uprv_realloc(buf, cap * sizeof(void*));
2226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (buf == NULL) {
2246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    // if we couldn't realloc, we leak the memory we've already allocated, but we're in deep trouble anyway
2256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    status = U_MEMORY_ALLOCATION_ERROR;
2266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return;
2276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
2286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                void* start = &buf[size];
2296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                size_t count = (cap - size) * sizeof(void*);
2306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                uprv_memset(start, 0, count); // fill with nulls, just because
2316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
2326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            buf[size++] = elem;
2336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
2346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void** release(void) {
2376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        void** result = buf;
2386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buf = NULL;
2396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        cap = 0;
2406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        size = 0;
2416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return result;
2426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass LocDataParser;
2466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass StringLocalizationInfo : public LocalizationInfo {
2486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar* info;
2496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar*** data;
2506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t numRuleSets;
2516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t numLocales;
2526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgfriend class LocDataParser;
2546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    StringLocalizationInfo(UChar* i, UChar*** d, int32_t numRS, int32_t numLocs)
2566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : info(i), data(d), numRuleSets(numRS), numLocales(numLocs)
2576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
2586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
2596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic:
2616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    static StringLocalizationInfo* create(const UnicodeString& info, UParseError& perror, UErrorCode& status);
2626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual ~StringLocalizationInfo();
2646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t getNumberOfRuleSets(void) const { return numRuleSets; }
2656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getRuleSetName(int32_t index) const;
2666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual int32_t getNumberOfDisplayLocales(void) const { return numLocales; }
2676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getLocaleName(int32_t index) const;
2686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    virtual const UChar* getDisplayName(int32_t localeIndex, int32_t ruleIndex) const;
2696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//    virtual UClassID getDynamicClassID() const;
2716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//    static UClassID getStaticClassID(void);
2726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgprivate:
2746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void init(UErrorCode& status) const;
2756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgenum {
2796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    OPEN_ANGLE = 0x003c, /* '<' */
2806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    CLOSE_ANGLE = 0x003e, /* '>' */
2816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    COMMA = 0x002c,
2826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TICK = 0x0027,
2836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    QUOTE = 0x0022,
2846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    SPACE = 0x0020
2856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
2866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
2886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Utility for parsing a localization string and returning a StringLocalizationInfo*.
2896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org */
2906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgclass LocDataParser {
2916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar* data;
2926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar* e;
2936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar* p;
2946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar ch;
2956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UParseError& pe;
2966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode& ec;
2976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
2986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgpublic:
2996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocDataParser(UParseError& parseError, UErrorCode& status)
3006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        : data(NULL), e(NULL), p(NULL), ch(0xffff), pe(parseError), ec(status) {}
3016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ~LocDataParser() {}
3026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /*
3046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * On a successful parse, return a StringLocalizationInfo*, otherwise delete locData, set perror and status,
3056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    * and return NULL.  The StringLocalizationInfo will adopt locData if it is created.
3066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    */
3076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    StringLocalizationInfo* parse(UChar* data, int32_t len);
3086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgprivate:
3106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void inc(void) { ++p; ch = 0xffff; }
3126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool checkInc(UChar c) { if (p < e && (ch == c || *p == c)) { inc(); return TRUE; } return FALSE; }
3136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool check(UChar c) { return p < e && (ch == c || *p == c); }
3146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void skipWhitespace(void) { while (p < e && PatternProps::isWhiteSpace(ch != 0xffff ? ch : *p)) inc();}
3156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool inList(UChar c, const UChar* list) const {
3166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (*list == SPACE && PatternProps::isWhiteSpace(c)) return TRUE;
3176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (*list && *list != c) ++list; return *list == c;
3186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    void parseError(const char* msg);
3206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    StringLocalizationInfo* doParse(void);
3226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar** nextArray(int32_t& requiredLength);
3246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar*  nextString(void);
3256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
3266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#ifdef DEBUG
3286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define ERROR(msg) parseError(msg); return NULL;
3296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#else
3306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#define ERROR(msg) parseError(NULL); return NULL;
3316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
3326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar DQUOTE_STOPLIST[] = {
3356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    QUOTE, 0
3366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
3376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar SQUOTE_STOPLIST[] = {
3396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    TICK, 0
3406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
3416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic const UChar NOQUOTE_STOPLIST[] = {
3436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    SPACE, COMMA, CLOSE_ANGLE, OPEN_ANGLE, TICK, QUOTE, 0
3446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org};
3456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgstatic void
3476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgDeleteFn(void* p) {
3486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  uprv_free(p);
3496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo*
3526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocDataParser::parse(UChar* _data, int32_t len) {
3536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(ec)) {
3546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (_data) uprv_free(_data);
3556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
3566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.line = 0;
3596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.offset = -1;
3606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.postContext[0] = 0;
3616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.preContext[0] = 0;
3626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (_data == NULL) {
3646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ec = U_ILLEGAL_ARGUMENT_ERROR;
3656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
3666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (len <= 0) {
3696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ec = U_ILLEGAL_ARGUMENT_ERROR;
3706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(_data);
3716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
3726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
3736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    data = _data;
3756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    e = data + len;
3766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p = _data;
3776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ch = 0xffff;
3786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return doParse();
3806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
3816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
3836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo*
3846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocDataParser::doParse(void) {
3856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    skipWhitespace();
3866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!checkInc(OPEN_ANGLE)) {
3876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ERROR("Missing open angle");
3886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
3896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        VArray array(DeleteFn);
3906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool mightHaveNext = TRUE;
3916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t requiredLength = -1;
3926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (mightHaveNext) {
3936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            mightHaveNext = FALSE;
3946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar** elem = nextArray(requiredLength);
3956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            skipWhitespace();
3966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UBool haveComma = check(COMMA);
3976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (elem) {
3986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                array.add(elem, ec);
3996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (haveComma) {
4006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    inc();
4016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    mightHaveNext = TRUE;
4026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
4036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if (haveComma) {
4046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ERROR("Unexpected character");
4056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        skipWhitespace();
4096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!checkInc(CLOSE_ANGLE)) {
4106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (check(OPEN_ANGLE)) {
4116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ERROR("Missing comma in outer array");
4126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
4136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ERROR("Missing close angle bracket in outer array");
4146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        skipWhitespace();
4186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (p != e) {
4196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Extra text after close of localization data");
4206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        array.add(NULL, ec);
4236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(ec)) {
4246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t numLocs = array.length() - 2; // subtract first, NULL
4256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UChar*** result = (UChar***)array.release();
4266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return new StringLocalizationInfo(data, result, requiredLength-2, numLocs); // subtract first, NULL
4286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ERROR("Unknown error");
4326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUChar**
4356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocDataParser::nextArray(int32_t& requiredLength) {
4366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(ec)) {
4376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
4386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    skipWhitespace();
4416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!checkInc(OPEN_ANGLE)) {
4426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ERROR("Missing open angle");
4436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    VArray array;
4466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UBool mightHaveNext = TRUE;
4476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (mightHaveNext) {
4486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        mightHaveNext = FALSE;
4496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar* elem = nextString();
4506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        skipWhitespace();
4516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool haveComma = check(COMMA);
4526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (elem) {
4536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            array.add(elem, ec);
4546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (haveComma) {
4556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                inc();
4566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                mightHaveNext = TRUE;
4576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
4586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (haveComma) {
4596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Unexpected comma");
4606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    skipWhitespace();
4636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!checkInc(CLOSE_ANGLE)) {
4646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (check(OPEN_ANGLE)) {
4656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Missing close angle bracket in inner array");
4666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
4676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Missing comma in inner array");
4686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    array.add(NULL, ec);
4726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(ec)) {
4736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (requiredLength == -1) {
4746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            requiredLength = array.length() + 1;
4756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (array.length() != requiredLength) {
4766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ec = U_ILLEGAL_ARGUMENT_ERROR;
4776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Array not of required length");
4786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
4796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return (UChar**)array.release();
4816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
4826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ERROR("Unknown Error");
4836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
4846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUChar*
4866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocDataParser::nextString() {
4876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar* result = NULL;
4886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
4896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    skipWhitespace();
4906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (p < e) {
4916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const UChar* terminators;
4926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar c = *p;
4936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UBool haveQuote = c == QUOTE || c == TICK;
4946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (haveQuote) {
4956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            inc();
4966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            terminators = c == QUOTE ? DQUOTE_STOPLIST : SQUOTE_STOPLIST;
4976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
4986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            terminators = NOQUOTE_STOPLIST;
4996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar* start = p;
5016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (p < e && !inList(*p, terminators)) ++p;
5026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (p == e) {
5036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Unexpected end of data");
5046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar x = *p;
5076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (p > start) {
5086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ch = x;
5096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            *p = 0x0; // terminate by writing to data
5106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result = start; // just point into data
5116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (haveQuote) {
5136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (x != c) {
5146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ERROR("Missing matching quote");
5156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if (p == start) {
5166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ERROR("Empty string");
5176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
5186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            inc();
5196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (x == OPEN_ANGLE || x == TICK || x == QUOTE) {
5206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ERROR("Unexpected character in string");
5216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // ok for there to be no next string
5256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
5266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
5296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocDataParser::parseError(const char* /*str*/) {
5306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!data) {
5316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
5326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar* start = p - U_PARSE_CONTEXT_LEN - 1;
5356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (start < data) {
5366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        start = data;
5376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (UChar* x = p; --x >= start;) {
5396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (!*x) {
5406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = x+1;
5416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            break;
5426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
5436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UChar* limit = p + U_PARSE_CONTEXT_LEN - 1;
5456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (limit > e) {
5466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        limit = e;
5476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_strncpy(pe.preContext, start, (int32_t)(p-start));
5496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.preContext[p-start] = 0;
5506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    u_strncpy(pe.postContext, p, (int32_t)(limit-p));
5516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.postContext[limit-p] = 0;
5526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    pe.offset = (int32_t)(p - data);
5536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#ifdef DEBUG
5556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fprintf(stderr, "%s at or near character %d: ", str, p-data);
5566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString msg;
5586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.append(start, p - start);
5596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.append((UChar)0x002f); /* SOLIDUS/SLASH */
5606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.append(p, limit-p);
5616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    msg.append("'");
5626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    char buf[128];
5646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t len = msg.extract(0, msg.length(), buf, 128);
5656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (len >= 128) {
5666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buf[127] = 0;
5676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
5686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        buf[len] = 0;
5696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fprintf(stderr, "%s\n", buf);
5716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    fflush(stderr);
5726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
5736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_free(data);
5756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    data = NULL;
5766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    p = NULL;
5776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    e = NULL;
5786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(ec)) {
5806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ec = U_PARSE_ERROR;
5816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
5836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//UOBJECT_DEFINE_RTTI_IMPLEMENTATION(StringLocalizationInfo)
5856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo*
5876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo::create(const UnicodeString& info, UParseError& perror, UErrorCode& status) {
5886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
5896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
5906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t len = info.length();
5936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (len == 0) {
5946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL; // no error;
5956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
5966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
5976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UChar* p = (UChar*)uprv_malloc(len * sizeof(UChar));
5986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!p) {
5996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
6006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
6016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    info.extract(p, len, status);
6036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!U_FAILURE(status)) {
6046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_ZERO_ERROR; // clear warning about non-termination
6056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocDataParser parser(perror, status);
6086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return parser.parse(p, len);
6096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo::~StringLocalizationInfo() {
6126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (UChar*** p = (UChar***)data; *p; ++p) {
6136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // remaining data is simply pointer into our unicode string data.
6146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (*p) uprv_free(*p);
6156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (data) uprv_free(data);
6176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (info) uprv_free(info);
6186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst UChar*
6226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo::getRuleSetName(int32_t index) const {
6236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (index >= 0 && index < getNumberOfRuleSets()) {
6246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return data[0][index];
6256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
6276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst UChar*
6306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo::getLocaleName(int32_t index) const {
6316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (index >= 0 && index < getNumberOfDisplayLocales()) {
6326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return data[index+1][0];
6336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
6356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgconst UChar*
6386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgStringLocalizationInfo::getDisplayName(int32_t localeIndex, int32_t ruleIndex) const {
6396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localeIndex >= 0 && localeIndex < getNumberOfDisplayLocales() &&
6406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ruleIndex >= 0 && ruleIndex < getNumberOfRuleSets()) {
6416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return data[localeIndex+1][ruleIndex+1];
6426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
6436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
6446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// ----------
6476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
6496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             const UnicodeString& locs,
6506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
6516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
6526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
6536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
6546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
6556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(alocale)
6566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
6576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
6586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
6596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
6606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
6616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
6636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  init(description, locinfo, perror, status);
6646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
6676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             const UnicodeString& locs,
6686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             UParseError& perror, UErrorCode& status)
6696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
6706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
6716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
6726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
6736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(Locale::getDefault())
6746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
6756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
6766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
6776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
6786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
6796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  LocalizationInfo* locinfo = StringLocalizationInfo::create(locs, perror, status);
6816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  init(description, locinfo, perror, status);
6826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
6836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
6846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
6856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             LocalizationInfo* info,
6866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                                             const Locale& alocale, UParseError& perror, UErrorCode& status)
6876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
6886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
6896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
6906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
6916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(alocale)
6926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
6936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
6946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
6956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
6966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
6976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
6986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  init(description, info, perror, status);
6996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
7026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UParseError& perror,
7036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode& status)
7046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
7056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
7066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
7076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
7086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(Locale::getDefault())
7096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
7106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
7116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
7126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
7136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
7146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    init(description, NULL, perror, status);
7166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const UnicodeString& description,
7196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         const Locale& aLocale,
7206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UParseError& perror,
7216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                         UErrorCode& status)
7226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
7236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
7246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
7256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
7266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(aLocale)
7276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
7286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
7296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
7306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
7316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
7326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    init(description, NULL, perror, status);
7346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(URBNFRuleSetTag tag, const Locale& alocale, UErrorCode& status)
7376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : ruleSets(NULL)
7386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
7396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
7406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
7416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(alocale)
7426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
7436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
7446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
7456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
7466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
7476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
7486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
7496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
7506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char* rules_tag = "RBNFRules";
7536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const char* fmt_tag = "";
7546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    switch (tag) {
7556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URBNF_SPELLOUT: fmt_tag = "SpelloutRules"; break;
7566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URBNF_ORDINAL: fmt_tag = "OrdinalRules"; break;
7576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URBNF_DURATION: fmt_tag = "DurationRules"; break;
7586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    case URBNF_NUMBERING_SYSTEM: fmt_tag = "NumberingSystemRules"; break;
7596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    default: status = U_ILLEGAL_ARGUMENT_ERROR; return;
7606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // TODO: read localization info from resource
7636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    LocalizationInfo* locinfo = NULL;
7646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UResourceBundle* nfrb = ures_open(U_ICUDATA_RBNF, locale.getName(), &status);
7666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
7676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        setLocaleIDs(ures_getLocaleByType(nfrb, ULOC_VALID_LOCALE, &status),
7686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                     ures_getLocaleByType(nfrb, ULOC_ACTUAL_LOCALE, &status));
7696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UResourceBundle* rbnfRules = ures_getByKeyWithFallback(nfrb, rules_tag, NULL, &status);
7716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_FAILURE(status)) {
7726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ures_close(nfrb);
7736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UResourceBundle* ruleSets = ures_getByKeyWithFallback(rbnfRules, fmt_tag, NULL, &status);
7756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_FAILURE(status)) {
7766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ures_close(rbnfRules);
7776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ures_close(nfrb);
7786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
7796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString desc;
7826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (ures_hasNext(ruleSets)) {
7836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org           desc.append(ures_getNextUnicodeString(ruleSets,NULL,&status));
7846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
7856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UParseError perror;
7866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        init (desc, locinfo, perror, status);
7886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ures_close(ruleSets);
7906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ures_close(rbnfRules);
7916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
7926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ures_close(nfrb);
7936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
7946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
7956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::RuleBasedNumberFormat(const RuleBasedNumberFormat& rhs)
7966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  : NumberFormat(rhs)
7976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSets(NULL)
7986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , ruleSetDescriptions(NULL)
7996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , numRuleSets(0)
8006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , defaultRuleSet(NULL)
8016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , locale(rhs.locale)
8026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , collator(NULL)
8036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , decimalFormatSymbols(NULL)
8046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenient(FALSE)
8056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , lenientParseRules(NULL)
8066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  , localizations(NULL)
8076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->operator=(rhs);
8096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// --------
8126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat&
8146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::operator=(const RuleBasedNumberFormat& rhs)
8156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
8176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    dispose();
8186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    locale = rhs.locale;
8196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lenient = rhs.lenient;
8206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString rules = rhs.getRules();
8226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UParseError perror;
8236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    init(rules, rhs.localizations ? rhs.localizations->ref() : NULL, perror, status);
8246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return *this;
8266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::~RuleBasedNumberFormat()
8296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    dispose();
8316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgFormat*
8346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::clone(void) const
8356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    RuleBasedNumberFormat * result = NULL;
8376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString rules = getRules();
8386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UErrorCode status = U_ZERO_ERROR;
8396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UParseError perror;
8406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result = new RuleBasedNumberFormat(rules, localizations, locale, perror, status);
8416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* test for NULL */
8426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (result == 0) {
8436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
8446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return 0;
8456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
8476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete result;
8486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result = 0;
8496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
8506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        result->lenient = lenient;
8516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
8536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUBool
8566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::operator==(const Format& other) const
8576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (this == &other) {
8596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return TRUE;
8606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (typeid(*this) == typeid(other)) {
8636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        const RuleBasedNumberFormat& rhs = (const RuleBasedNumberFormat&)other;
8646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (locale == rhs.locale &&
8656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lenient == rhs.lenient &&
8666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (localizations == NULL
8676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ? rhs.localizations == NULL
8686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                : (rhs.localizations == NULL
8696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    ? FALSE
8706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    : *localizations == rhs.localizations))) {
8716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet** p = ruleSets;
8736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet** q = rhs.ruleSets;
8746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (p == NULL) {
8756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return q == NULL;
8766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else if (q == NULL) {
8776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return FALSE;
8786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (*p && *q && (**p == **q)) {
8806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++p;
8816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++q;
8826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
8836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return *q == NULL && *p == NULL;
8846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return FALSE;
8886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
8896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
8906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
8916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getRules() const
8926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
8936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString result;
8946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleSets != NULL) {
8956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (NFRuleSet** p = ruleSets; *p; ++p) {
8966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            (*p)->appendRules(result);
8976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
8986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
8996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
9006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
9036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getRuleSetName(int32_t index) const
9046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
9056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations) {
9066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      UnicodeString string(TRUE, localizations->getRuleSetName(index), (int32_t)-1);
9076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      return string;
9086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if (ruleSets) {
9096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString result;
9106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (NFRuleSet** p = ruleSets; *p; ++p) {
9116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet* rs = *p;
9126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs->isPublic()) {
9136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (--index == -1) {
9146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    rs->getName(result);
9156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    return result;
9166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
9176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString empty;
9216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return empty;
9226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
9256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getNumberOfRuleSetNames() const
9266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
9276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t result = 0;
9286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations) {
9296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      result = localizations->getNumberOfRuleSets();
9306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if (ruleSets) {
9316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (NFRuleSet** p = ruleSets; *p; ++p) {
9326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if ((**p).isPublic()) {
9336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++result;
9346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return result;
9386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgint32_t
9416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getNumberOfRuleSetDisplayNameLocales(void) const {
9426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations) {
9436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return localizations->getNumberOfDisplayLocales();
9446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return 0;
9466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgLocale
9496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getRuleSetDisplayNameLocale(int32_t index, UErrorCode& status) const {
9506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
9516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return Locale("");
9526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations && index >= 0 && index < localizations->getNumberOfDisplayLocales()) {
9546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString name(TRUE, localizations->getLocaleName(index), -1);
9556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char buffer[64];
9566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t cap = name.length() + 1;
9576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        char* bp = buffer;
9586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (cap > 64) {
9596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            bp = (char *)uprv_malloc(cap);
9606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (bp == NULL) {
9616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                status = U_MEMORY_ALLOCATION_ERROR;
9626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return Locale("");
9636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        name.extract(0, name.length(), bp, cap, UnicodeString::kInvariant);
9666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Locale retLocale(bp);
9676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (bp != buffer) {
9686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            uprv_free(bp);
9696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return retLocale;
9716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    status = U_ILLEGAL_ARGUMENT_ERROR;
9736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Locale retLocale;
9746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return retLocale;
9756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
9766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
9786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getRuleSetDisplayName(int32_t index, const Locale& localeParam) {
9796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations && index >= 0 && index < localizations->getNumberOfRuleSets()) {
9806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString localeName(localeParam.getBaseName(), -1, UnicodeString::kInvariant);
9816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t len = localeName.length();
9826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UChar* localeStr = localeName.getBuffer(len + 1);
9836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (len >= 0) {
9846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            localeStr[len] = 0;
9856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int32_t ix = localizations->indexForLocale(localeStr);
9866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ix >= 0) {
9876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UnicodeString name(TRUE, localizations->getDisplayName(ix, index), -1);
9886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return name;
9896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
9906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
9916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // trim trailing portion, skipping over ommitted sections
9926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            do { --len;} while (len > 0 && localeStr[len] != 0x005f); // underscore
9936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (len > 0 && localeStr[len-1] == 0x005F) --len;
9946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
9956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString name(TRUE, localizations->getRuleSetName(index), -1);
9966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return name;
9976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
9986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString bogus;
9996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    bogus.setToBogus();
10006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return bogus;
10016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
10046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getRuleSetDisplayName(const UnicodeString& ruleSetName, const Locale& localeParam) {
10056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations) {
10066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UnicodeString rsn(ruleSetName);
10076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t ix = localizations->indexForRuleSet(rsn.getTerminatedBuffer());
10086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return getRuleSetDisplayName(ix, localeParam);
10096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString bogus;
10116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    bogus.setToBogus();
10126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return bogus;
10136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgNFRuleSet*
10166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::findRuleSet(const UnicodeString& name, UErrorCode& status) const
10176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status) && ruleSets) {
10196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (NFRuleSet** p = ruleSets; *p; ++p) {
10206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet* rs = *p;
10216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs->isNamed(name)) {
10226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return rs;
10236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_ILLEGAL_ARGUMENT_ERROR;
10266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return NULL;
10286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
10316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(int32_t number,
10326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
10336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */) const
10346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (defaultRuleSet) defaultRuleSet->format((int64_t)number, toAppendTo, toAppendTo.length());
10366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
10376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
10416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(int64_t number,
10426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
10436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */) const
10446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (defaultRuleSet) defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
10466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
10476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
10516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(double number,
10526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
10536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */) const
10546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Special case for NaN; adapted from what DecimalFormat::_format( double number,...) does.
10566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (uprv_isNaN(number)) {
10576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DecimalFormatSymbols* decFmtSyms = getDecimalFormatSymbols(); // RuleBasedNumberFormat internal
10586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (decFmtSyms) {
10596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            toAppendTo += decFmtSyms->getConstSymbol(DecimalFormatSymbols::kNaNSymbol);
10606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else if (defaultRuleSet) {
10626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        defaultRuleSet->format(number, toAppendTo, toAppendTo.length());
10636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
10656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
10696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(int32_t number,
10706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              const UnicodeString& ruleSetName,
10716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
10726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */,
10736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UErrorCode& status) const
10746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // return format((int64_t)number, ruleSetName, toAppendTo, pos, status);
10766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
10776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
10786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // throw new IllegalArgumentException("Can't use internal rule set");
10796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_ILLEGAL_ARGUMENT_ERROR;
10806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
10816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet *rs = findRuleSet(ruleSetName, status);
10826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs) {
10836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                rs->format((int64_t)number, toAppendTo, toAppendTo.length());
10846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
10856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
10866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
10876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
10886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
10896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
10916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
10926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(int64_t number,
10936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              const UnicodeString& ruleSetName,
10946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
10956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */,
10966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UErrorCode& status) const
10976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
10986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
10996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
11006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // throw new IllegalArgumentException("Can't use internal rule set");
11016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_ILLEGAL_ARGUMENT_ERROR;
11026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
11036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet *rs = findRuleSet(ruleSetName, status);
11046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs) {
11056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                rs->format(number, toAppendTo, toAppendTo.length());
11066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
11106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString&
11146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::format(double number,
11156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              const UnicodeString& ruleSetName,
11166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UnicodeString& toAppendTo,
11176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              FieldPosition& /* pos */,
11186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                              UErrorCode& status) const
11196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
11206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
11216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ruleSetName.indexOf(gPercentPercent, 2, 0) == 0) {
11226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // throw new IllegalArgumentException("Can't use internal rule set");
11236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_ILLEGAL_ARGUMENT_ERROR;
11246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
11256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet *rs = findRuleSet(ruleSetName, status);
11266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs) {
11276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                rs->format(number, toAppendTo, toAppendTo.length());
11286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return toAppendTo;
11326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::parse(const UnicodeString& text,
11366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             Formattable& result,
11376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                             ParsePosition& parsePosition) const
11386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
11396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!ruleSets) {
11406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parsePosition.setErrorIndex(0);
11416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
11426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString workingText(text, parsePosition.getIndex());
11456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ParsePosition workingPos(0);
11466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ParsePosition high_pp(0);
11486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    Formattable high_result;
11496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (NFRuleSet** p = ruleSets; *p; ++p) {
11516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        NFRuleSet *rp = *p;
11526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (rp->isPublic() && rp->isParseable()) {
11536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ParsePosition working_pp(0);
11546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            Formattable working_result;
11556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            rp->parse(workingText, working_pp, kMaxDouble, working_result);
11576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (working_pp.getIndex() > high_pp.getIndex()) {
11586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                high_pp = working_pp;
11596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                high_result = working_result;
11606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (high_pp.getIndex() == workingText.length()) {
11626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                    break;
11636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
11646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
11656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t startIndex = parsePosition.getIndex();
11696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    parsePosition.setIndex(startIndex + high_pp.getIndex());
11706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (high_pp.getIndex() > 0) {
11716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parsePosition.setErrorIndex(-1);
11726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
11736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t errorIndex = (high_pp.getErrorIndex()>0)? high_pp.getErrorIndex(): 0;
11746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        parsePosition.setErrorIndex(startIndex + errorIndex);
11756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result = high_result;
11776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (result.getType() == Formattable::kDouble) {
11786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t r = (int32_t)result.getDouble();
11796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if ((double)r == result.getDouble()) {
11806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result.setLong(r);
11816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
11826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_COLLATION
11866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
11886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::setLenient(UBool enabled)
11896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
11906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lenient = enabled;
11916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!enabled && collator) {
11926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete collator;
11936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        collator = NULL;
11946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
11956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
11966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
11986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
11996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
12006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::setDefaultRuleSet(const UnicodeString& ruleSetName, UErrorCode& status) {
12016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_SUCCESS(status)) {
12026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ruleSetName.isEmpty()) {
12036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          if (localizations) {
12046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              UnicodeString name(TRUE, localizations->getRuleSetName(0), -1);
12056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org              defaultRuleSet = findRuleSet(name, status);
12066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          } else {
12076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            initDefaultRuleSet();
12086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org          }
12096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else if (ruleSetName.startsWith(UNICODE_STRING_SIMPLE("%%"))) {
12106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_ILLEGAL_ARGUMENT_ERROR;
12116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
12126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet* result = findRuleSet(ruleSetName, status);
12136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (result != NULL) {
12146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                defaultRuleSet = result;
12156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgUnicodeString
12216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getDefaultRuleSetName() const {
12226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  UnicodeString result;
12236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  if (defaultRuleSet && defaultRuleSet->isPublic()) {
12246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    defaultRuleSet->getName(result);
12256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  } else {
12266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    result.setToBogus();
12276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  }
12286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org  return result;
12296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
12326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::initDefaultRuleSet()
12336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    defaultRuleSet = NULL;
12356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!ruleSets) {
12366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org      return;
12376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UnicodeString spellout = UNICODE_STRING_SIMPLE("%spellout-numbering");
12406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UnicodeString ordinal = UNICODE_STRING_SIMPLE("%digits-ordinal");
12416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    const UnicodeString duration = UNICODE_STRING_SIMPLE("%duration");
12426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    NFRuleSet**p = &ruleSets[0];
12446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (*p) {
12456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if ((*p)->isNamed(spellout) || (*p)->isNamed(ordinal) || (*p)->isNamed(duration)) {
12466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            defaultRuleSet = *p;
12476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
12486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
12496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++p;
12506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    defaultRuleSet = *--p;
12546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!defaultRuleSet->isPublic()) {
12556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (p != ruleSets) {
12566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if ((*--p)->isPublic()) {
12576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                defaultRuleSet = *p;
12586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break;
12596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
12606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
12616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
12636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
12666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::init(const UnicodeString& rules, LocalizationInfo* localizationInfos,
12676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                            UParseError& pErr, UErrorCode& status)
12686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
12696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // TODO: implement UParseError
12706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    uprv_memset(&pErr, 0, sizeof(UParseError));
12716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Note: this can leave ruleSets == NULL, so remaining code should check
12726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (U_FAILURE(status)) {
12736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
12746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    this->localizations = localizationInfos == NULL ? NULL : localizationInfos->ref();
12776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString description(rules);
12796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!description.length()) {
12806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
12816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
12826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
12836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // start by stripping the trailing whitespace from all the rules
12856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // (this is all the whitespace follwing each semicolon in the
12866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // description).  This allows us to look for rule-set boundaries
12876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // by searching for ";%" without having to worry about whitespace
12886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // between the ; and the %
12896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    stripWhitespace(description);
12906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
12916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // check to see if there's a set of lenient-parse rules.  If there
12926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // is, pull them out into our temporary holding place for them,
12936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // and delete them from the description before the real desciption-
12946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // parsing code sees them
12956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int32_t lp = description.indexOf(gLenientParse, -1, 0);
12966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (lp != -1) {
12976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // we've got to make sure we're not in the middle of a rule
12986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // (where "%%lenient-parse" would actually get treated as
12996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // rule text)
13006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (lp == 0 || description.charAt(lp - 1) == gSemiColon) {
13016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // locate the beginning and end of the actual collation
13026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // rules (there may be whitespace between the name and
13036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the first token in the description)
13046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int lpEnd = description.indexOf(gSemiPercent, 2, lp);
13056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lpEnd == -1) {
13076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                lpEnd = description.length() - 1;
13086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            int lpStart = lp + u_strlen(gLenientParse);
13106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            while (PatternProps::isWhiteSpace(description.charAt(lpStart))) {
13116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ++lpStart;
13126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // copy out the lenient-parse rules and delete them
13156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // from the description
13166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lenientParseRules = new UnicodeString();
13176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            /* test for NULL */
13186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lenientParseRules == 0) {
13196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                status = U_MEMORY_ALLOCATION_ERROR;
13206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
13216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            lenientParseRules->setTo(description, lpStart, lpEnd - lpStart);
13236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            description.remove(lp, lpEnd + 1 - lp);
13256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // pre-flight parsing the description and count the number of
13296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // rule sets (";%" marks the end of one rule set and the beginning
13306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // of the next)
13316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    numRuleSets = 0;
13326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, p)) {
13336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++numRuleSets;
13346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ++p;
13356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ++numRuleSets;
13376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // our rule list is an array of the appropriate size
13396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ruleSets = (NFRuleSet **)uprv_malloc((numRuleSets + 1) * sizeof(NFRuleSet *));
13406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    /* test for NULL */
13416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleSets == 0) {
13426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
13436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
13446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    for (int i = 0; i <= numRuleSets; ++i) {
13476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ruleSets[i] = NULL;
13486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // divide up the descriptions into individual rule-set descriptions
13516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // and store them in a temporary array.  At each step, we also
13526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // new up a rule set, but all this does is initialize its name
13536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // and remove it from its description.  We can't actually parse
13546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // the rest of the descriptions and finish initializing everything
13556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // because we have to know the names and locations of all the rule
13566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // sets before we can actually set everything up
13576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if(!numRuleSets) {
13586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_ILLEGAL_ARGUMENT_ERROR;
13596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
13606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    ruleSetDescriptions = new UnicodeString[numRuleSets];
13636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleSetDescriptions == 0) {
13646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        status = U_MEMORY_ALLOCATION_ERROR;
13656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return;
13666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
13696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int curRuleSet = 0;
13706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t start = 0;
13716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (int32_t p = description.indexOf(gSemiPercent, 2, 0); p != -1; p = description.indexOf(gSemiPercent, 2, start)) {
13726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ruleSetDescriptions[curRuleSet].setTo(description, start, p + 1 - start);
13736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
13746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (ruleSets[curRuleSet] == 0) {
13756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                status = U_MEMORY_ALLOCATION_ERROR;
13766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                return;
13776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
13786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++curRuleSet;
13796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = p + 1;
13806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ruleSetDescriptions[curRuleSet].setTo(description, start, description.length() - start);
13826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ruleSets[curRuleSet] = new NFRuleSet(ruleSetDescriptions, curRuleSet, status);
13836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (ruleSets[curRuleSet] == 0) {
13846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            status = U_MEMORY_ALLOCATION_ERROR;
13856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            return;
13866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
13876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
13886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // now we can take note of the formatter's default rule set, which
13906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // is the last public rule set in the description (it's the last
13916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // rather than the first so that a user can create a new formatter
13926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // from an existing formatter and change its default behavior just
13936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // by appending more rule sets to the end)
13946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
13956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // {dlf} Initialization of a fraction rule set requires the default rule
13966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // set to be known.  For purposes of initialization, this is always the
13976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // last public rule set, no matter what the localization data says.
13986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    initDefaultRuleSet();
13996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // finally, we can go back through the temporary descriptions
14016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // list and finish seting up the substructure (and we throw
14026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // away the temporary descriptions as we go)
14036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
14046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (int i = 0; i < numRuleSets; i++) {
14056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
14066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // Now that the rules are initialized, the 'real' default rule
14106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // set can be adjusted by the localization data.
14116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // The C code keeps the localization array as is, rather than building
14136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // a separate array of the public rule set names, so we have less work
14146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // to do here-- but we still need to check the names.
14156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizationInfos) {
14176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // confirm the names, if any aren't in the rules, that's an error
14186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // it is ok if the rules contain public rule sets that are not in this list
14196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (int32_t i = 0; i < localizationInfos->getNumberOfRuleSets(); ++i) {
14206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            UnicodeString name(TRUE, localizationInfos->getRuleSetName(i), -1);
14216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            NFRuleSet* rs = findRuleSet(name, status);
14226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (rs == NULL) {
14236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                break; // error
14246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (i == 0) {
14266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                defaultRuleSet = rs;
14276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
14286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    } else {
14306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        defaultRuleSet = getDefaultRuleSet();
14316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
14336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
14356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::stripWhitespace(UnicodeString& description)
14366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
14376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // iterate through the characters...
14386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    UnicodeString result;
14396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    int start = 0;
14416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    while (start != -1 && start < description.length()) {
14426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // seek to the first non-whitespace character...
14436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        while (start < description.length()
14446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            && PatternProps::isWhiteSpace(description.charAt(start))) {
14456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ++start;
14466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // locate the next semicolon in the text and copy the text from
14496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // our current position up to that semicolon into the result
14506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        int32_t p = description.indexOf(gSemiColon, start);
14516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (p == -1) {
14526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // or if we don't find a semicolon, just copy the rest of
14536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            // the string into the result
14546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result.append(description, start, description.length() - start);
14556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = -1;
14566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        else if (p < description.length()) {
14586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            result.append(description, start, p + 1 - start);
14596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = p + 1;
14606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // when we get here, we've seeked off the end of the sring, and
14636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // we terminate the loop (we continue until *start* is -1 rather
14646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // than until *p* is -1, because otherwise we'd miss the last
14656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // rule in the description)
14666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        else {
14676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            start = -1;
14686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    description.setTo(result);
14726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
14736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
14766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::dispose()
14776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
14786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleSets) {
14796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (NFRuleSet** p = ruleSets; *p; ++p) {
14806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete *p;
14816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
14826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        uprv_free(ruleSets);
14836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        ruleSets = NULL;
14846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (ruleSetDescriptions) {
14876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete [] ruleSetDescriptions;
14886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
14896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_COLLATION
14916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete collator;
14926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
14936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    collator = NULL;
14946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete decimalFormatSymbols;
14966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    decimalFormatSymbols = NULL;
14976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
14986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    delete lenientParseRules;
14996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    lenientParseRules = NULL;
15006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (localizations) localizations = localizations->unref();
15026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
15036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//-----------------------------------------------------------------------
15066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// package-internal API
15076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org//-----------------------------------------------------------------------
15086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
15106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Returns the collator to use for lenient parsing.  The collator is lazily created:
15116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * this function creates it the first time it's called.
15126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return The collator to use for lenient parsing, or null if lenient parsing
15136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * is turned off.
15146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
15156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgCollator*
15166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getCollator() const
15176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
15186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#if !UCONFIG_NO_COLLATION
15196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (!ruleSets) {
15206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return NULL;
15216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // lazy-evaulate the collator
15246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (collator == NULL && lenient) {
15256f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // create a default collator based on the formatter's locale,
15266f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // then pull out that collator's rules, append any additional
15276f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // rules specified in the description, and create a _new_
15286f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // collator based on the combinaiton of those rules
15296f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15306f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode status = U_ZERO_ERROR;
15316f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15326f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        Collator* temp = Collator::createInstance(locale, status);
15336f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        RuleBasedCollator* newCollator;
15346f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(status) && (newCollator = dynamic_cast<RuleBasedCollator*>(temp)) != NULL) {
15356f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (lenientParseRules) {
15366f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                UnicodeString rules(newCollator->getRules());
15376f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                rules.append(*lenientParseRules);
15386f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15396f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newCollator = new RuleBasedCollator(rules, status);
15406f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // Exit if newCollator could not be created.
15416f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                if (newCollator == NULL) {
15426f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                	return NULL;
15436f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                }
15446f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
15456f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                temp = NULL;
15466f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15476f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            if (U_SUCCESS(status)) {
15486f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                newCollator->setAttribute(UCOL_DECOMPOSITION_MODE, UCOL_ON, status);
15496f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                // cast away const
15506f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                ((RuleBasedNumberFormat*)this)->collator = newCollator;
15516f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            } else {
15526f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org                delete newCollator;
15536f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            }
15546f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
15556f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete temp;
15566f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15576f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
15586f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15596f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // if lenient-parse mode is off, this will be null
15606f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // (see setLenientParseMode())
15616f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return collator;
15626f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
15636f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15646f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15656f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/**
15666f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * Returns the DecimalFormatSymbols object that should be used by all DecimalFormat
15676f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * instances owned by this formatter.  This object is lazily created: this function
15686f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * creates it the first time it's called.
15696f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * @return The DecimalFormatSymbols object that should be used by all DecimalFormat
15706f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org * instances owned by this formatter.
15716f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org*/
15726f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgDecimalFormatSymbols*
15736f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::getDecimalFormatSymbols() const
15746f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
15756f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // lazy-evaluate the DecimalFormatSymbols object.  This object
15766f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // is shared by all DecimalFormat instances belonging to this
15776f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    // formatter
15786f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (decimalFormatSymbols == NULL) {
15796f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode status = U_ZERO_ERROR;
15806f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        DecimalFormatSymbols* temp = new DecimalFormatSymbols(locale, status);
15816f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        if (U_SUCCESS(status)) {
15826f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ((RuleBasedNumberFormat*)this)->decimalFormatSymbols = temp;
15836f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        } else {
15846f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            delete temp;
15856f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
15866f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15876f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    return decimalFormatSymbols;
15886f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
15896f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15906f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// De-owning the current localized symbols and adopt the new symbols.
15916f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
15926f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::adoptDecimalFormatSymbols(DecimalFormatSymbols* symbolsToAdopt)
15936f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
15946f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (symbolsToAdopt == NULL) {
15956f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        return; // do not allow caller to set decimalFormatSymbols to NULL
15966f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
15976f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
15986f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    if (decimalFormatSymbols != NULL) {
15996f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        delete decimalFormatSymbols;
16006f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16016f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16026f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    decimalFormatSymbols = symbolsToAdopt;
16036f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16046f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    {
16056f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        // Apply the new decimalFormatSymbols by reparsing the rulesets
16066f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        UErrorCode status = U_ZERO_ERROR;
16076f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16086f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        for (int32_t i = 0; i < numRuleSets; i++) {
16096f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org            ruleSets[i]->parseRules(ruleSetDescriptions[i], this, status);
16106f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org        }
16116f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    }
16126f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16136f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16146f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org// Setting the symbols is equlivalent to adopting a newly created localized symbols.
16156f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgvoid
16166f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgRuleBasedNumberFormat::setDecimalFormatSymbols(const DecimalFormatSymbols& symbols)
16176f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org{
16186f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org    adoptDecimalFormatSymbols(new DecimalFormatSymbols(symbols));
16196f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org}
16206f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16216f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.orgU_NAMESPACE_END
16226f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org
16236f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org/* U_HAVE_RBNF */
16246f31ac30b9092fd02a8c97e5216cf53f3e4fae4jshin@chromium.org#endif
1625