Home | History | Annotate | Download | only in i18n
      1 //  2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 **********************************************************************
      5 * Copyright (c) 2004-2016, International Business Machines
      6 * Corporation and others.  All Rights Reserved.
      7 **********************************************************************
      8 * Author: Alan Liu
      9 * Created: April 20, 2004
     10 * Since: ICU 3.0
     11 **********************************************************************
     12 */
     13 #include "utypeinfo.h"  // for 'typeid' to work
     14 #include "unicode/utypes.h"
     15 
     16 #if !UCONFIG_NO_FORMATTING
     17 
     18 #include "unicode/measfmt.h"
     19 #include "unicode/numfmt.h"
     20 #include "currfmt.h"
     21 #include "unicode/localpointer.h"
     22 #include "resource.h"
     23 #include "unicode/simpleformatter.h"
     24 #include "quantityformatter.h"
     25 #include "unicode/plurrule.h"
     26 #include "unicode/decimfmt.h"
     27 #include "uresimp.h"
     28 #include "unicode/ures.h"
     29 #include "unicode/ustring.h"
     30 #include "ureslocs.h"
     31 #include "cstring.h"
     32 #include "mutex.h"
     33 #include "ucln_in.h"
     34 #include "unicode/listformatter.h"
     35 #include "charstr.h"
     36 #include "unicode/putil.h"
     37 #include "unicode/smpdtfmt.h"
     38 #include "uassert.h"
     39 
     40 #include "sharednumberformat.h"
     41 #include "sharedpluralrules.h"
     42 #include "standardplural.h"
     43 #include "unifiedcache.h"
     44 
     45 
     46 U_NAMESPACE_BEGIN
     47 
     48 static constexpr int32_t PER_UNIT_INDEX = StandardPlural::COUNT;
     49 static constexpr int32_t PATTERN_COUNT = PER_UNIT_INDEX + 1;
     50 static constexpr int32_t MEAS_UNIT_COUNT = 138;  // see assertion in MeasureFormatCacheData constructor
     51 static constexpr int32_t WIDTH_INDEX_COUNT = UMEASFMT_WIDTH_NARROW + 1;
     52 
     53 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat)
     54 
     55 // Used to format durations like 5:47 or 21:35:42.
     56 class NumericDateFormatters : public UMemory {
     57 public:
     58     // Formats like H:mm
     59     SimpleDateFormat hourMinute;
     60 
     61     // formats like M:ss
     62     SimpleDateFormat minuteSecond;
     63 
     64     // formats like H:mm:ss
     65     SimpleDateFormat hourMinuteSecond;
     66 
     67     // Constructor that takes the actual patterns for hour-minute,
     68     // minute-second, and hour-minute-second respectively.
     69     NumericDateFormatters(
     70             const UnicodeString &hm,
     71             const UnicodeString &ms,
     72             const UnicodeString &hms,
     73             UErrorCode &status) :
     74             hourMinute(hm, status),
     75             minuteSecond(ms, status),
     76             hourMinuteSecond(hms, status) {
     77         const TimeZone *gmt = TimeZone::getGMT();
     78         hourMinute.setTimeZone(*gmt);
     79         minuteSecond.setTimeZone(*gmt);
     80         hourMinuteSecond.setTimeZone(*gmt);
     81     }
     82 private:
     83     NumericDateFormatters(const NumericDateFormatters &other);
     84     NumericDateFormatters &operator=(const NumericDateFormatters &other);
     85 };
     86 
     87 static UMeasureFormatWidth getRegularWidth(UMeasureFormatWidth width) {
     88     if (width >= WIDTH_INDEX_COUNT) {
     89         return UMEASFMT_WIDTH_NARROW;
     90     }
     91     return width;
     92 }
     93 
     94 /**
     95  * Instances contain all MeasureFormat specific data for a particular locale.
     96  * This data is cached. It is never copied, but is shared via shared pointers.
     97  *
     98  * Note: We might change the cache data to have an array[WIDTH_INDEX_COUNT] of
     99  * complete sets of unit & per patterns,
    100  * to correspond to the resource data and its aliases.
    101  *
    102  * TODO: Maybe store more sparsely in general, with pointers rather than potentially-empty objects.
    103  */
    104 class MeasureFormatCacheData : public SharedObject {
    105 public:
    106 
    107     /**
    108      * Redirection data from root-bundle, top-level sideways aliases.
    109      * - UMEASFMT_WIDTH_COUNT: initial value, just fall back to root
    110      * - UMEASFMT_WIDTH_WIDE/SHORT/NARROW: sideways alias for missing data
    111      */
    112     UMeasureFormatWidth widthFallback[WIDTH_INDEX_COUNT];
    113     /** Measure unit -> format width -> array of patterns ("{0} meters") (plurals + PER_UNIT_INDEX) */
    114     SimpleFormatter* patterns[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT][PATTERN_COUNT];
    115     const UChar* dnams[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT];
    116     SimpleFormatter perFormatters[WIDTH_INDEX_COUNT];
    117 
    118     MeasureFormatCacheData();
    119     virtual ~MeasureFormatCacheData();
    120 
    121     UBool hasPerFormatter(int32_t width) const {
    122         // TODO: Create a more obvious way to test if the per-formatter has been set?
    123         // Use pointers, check for NULL? Or add an isValid() method?
    124         return perFormatters[width].getArgumentLimit() == 2;
    125     }
    126 
    127     void adoptCurrencyFormat(int32_t widthIndex, NumberFormat *nfToAdopt) {
    128         delete currencyFormats[widthIndex];
    129         currencyFormats[widthIndex] = nfToAdopt;
    130     }
    131     const NumberFormat *getCurrencyFormat(UMeasureFormatWidth width) const {
    132         return currencyFormats[getRegularWidth(width)];
    133     }
    134     void adoptIntegerFormat(NumberFormat *nfToAdopt) {
    135         delete integerFormat;
    136         integerFormat = nfToAdopt;
    137     }
    138     const NumberFormat *getIntegerFormat() const {
    139         return integerFormat;
    140     }
    141     void adoptNumericDateFormatters(NumericDateFormatters *formattersToAdopt) {
    142         delete numericDateFormatters;
    143         numericDateFormatters = formattersToAdopt;
    144     }
    145     const NumericDateFormatters *getNumericDateFormatters() const {
    146         return numericDateFormatters;
    147     }
    148 
    149 private:
    150     NumberFormat* currencyFormats[WIDTH_INDEX_COUNT];
    151     NumberFormat* integerFormat;
    152     NumericDateFormatters* numericDateFormatters;
    153 
    154     MeasureFormatCacheData(const MeasureFormatCacheData &other);
    155     MeasureFormatCacheData &operator=(const MeasureFormatCacheData &other);
    156 };
    157 
    158 MeasureFormatCacheData::MeasureFormatCacheData()
    159         : integerFormat(nullptr), numericDateFormatters(nullptr) {
    160     // Please update MEAS_UNIT_COUNT if it gets out of sync with the true count!
    161     U_ASSERT(MEAS_UNIT_COUNT == MeasureUnit::getIndexCount());
    162 
    163     for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) {
    164         widthFallback[i] = UMEASFMT_WIDTH_COUNT;
    165     }
    166     memset(&patterns[0][0][0], 0, sizeof(patterns));
    167     memset(&dnams[0][0], 0, sizeof(dnams));
    168     memset(currencyFormats, 0, sizeof(currencyFormats));
    169 }
    170 
    171 MeasureFormatCacheData::~MeasureFormatCacheData() {
    172     for (int32_t i = 0; i < UPRV_LENGTHOF(currencyFormats); ++i) {
    173         delete currencyFormats[i];
    174     }
    175     for (int32_t i = 0; i < MEAS_UNIT_COUNT; ++i) {
    176         for (int32_t j = 0; j < WIDTH_INDEX_COUNT; ++j) {
    177             for (int32_t k = 0; k < PATTERN_COUNT; ++k) {
    178                 delete patterns[i][j][k];
    179             }
    180         }
    181     }
    182     // Note: the contents of 'dnams' are pointers into the resource bundle
    183     delete integerFormat;
    184     delete numericDateFormatters;
    185 }
    186 
    187 static UBool isCurrency(const MeasureUnit &unit) {
    188     return (uprv_strcmp(unit.getType(), "currency") == 0);
    189 }
    190 
    191 static UBool getString(
    192         const UResourceBundle *resource,
    193         UnicodeString &result,
    194         UErrorCode &status) {
    195     int32_t len = 0;
    196     const UChar *resStr = ures_getString(resource, &len, &status);
    197     if (U_FAILURE(status)) {
    198         return FALSE;
    199     }
    200     result.setTo(TRUE, resStr, len);
    201     return TRUE;
    202 }
    203 
    204 namespace {
    205 
    206 static const UChar g_LOCALE_units[] = {
    207     0x2F, 0x4C, 0x4F, 0x43, 0x41, 0x4C, 0x45, 0x2F,
    208     0x75, 0x6E, 0x69, 0x74, 0x73
    209 };
    210 static const UChar gShort[] = { 0x53, 0x68, 0x6F, 0x72, 0x74 };
    211 static const UChar gNarrow[] = { 0x4E, 0x61, 0x72, 0x72, 0x6F, 0x77 };
    212 
    213 /**
    214  * Sink for enumerating all of the measurement unit display names.
    215  * Contains inner sink classes, each one corresponding to a type of resource table.
    216  * The outer sink handles the top-level units, unitsNarrow, and unitsShort tables.
    217  *
    218  * More specific bundles (en_GB) are enumerated before their parents (en_001, en, root):
    219  * Only store a value if it is still missing, that is, it has not been overridden.
    220  *
    221  * C++: Each inner sink class has a reference to the main outer sink.
    222  * Java: Use non-static inner classes instead.
    223  */
    224 struct UnitDataSink : public ResourceSink {
    225 
    226     // Output data.
    227     MeasureFormatCacheData &cacheData;
    228 
    229     // Path to current data.
    230     UMeasureFormatWidth width;
    231     const char *type;
    232     int32_t unitIndex;
    233 
    234     UnitDataSink(MeasureFormatCacheData &outputData)
    235             : cacheData(outputData),
    236               width(UMEASFMT_WIDTH_COUNT), type(NULL), unitIndex(0) {}
    237     ~UnitDataSink();
    238 
    239     void setFormatterIfAbsent(int32_t index, const ResourceValue &value,
    240                                 int32_t minPlaceholders, UErrorCode &errorCode) {
    241         U_ASSERT(unitIndex < MEAS_UNIT_COUNT);
    242         U_ASSERT(width < WIDTH_INDEX_COUNT);
    243         U_ASSERT(index < PATTERN_COUNT);
    244         SimpleFormatter **patterns = &cacheData.patterns[unitIndex][width][0];
    245         if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
    246             if (minPlaceholders >= 0) {
    247                 patterns[index] = new SimpleFormatter(
    248                         value.getUnicodeString(errorCode), minPlaceholders, 1, errorCode);
    249             }
    250             if (U_SUCCESS(errorCode) && patterns[index] == NULL) {
    251                 errorCode = U_MEMORY_ALLOCATION_ERROR;
    252             }
    253         }
    254     }
    255 
    256     void setDnamIfAbsent(const ResourceValue &value, UErrorCode& errorCode) {
    257         U_ASSERT(unitIndex < MEAS_UNIT_COUNT);
    258         U_ASSERT(width < WIDTH_INDEX_COUNT);
    259         if (cacheData.dnams[unitIndex][width] == NULL) {
    260             int32_t length;
    261             cacheData.dnams[unitIndex][width] = value.getString(length, errorCode);
    262         }
    263     }
    264 
    265     /**
    266      * Consume a display pattern. For example,
    267      * unitsShort/duration/hour contains other{"{0} hrs"}.
    268      */
    269     void consumePattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
    270         if (U_FAILURE(errorCode)) { return; }
    271         if (uprv_strcmp(key, "dnam") == 0) {
    272             // The display name for the unit in the current width.
    273             setDnamIfAbsent(value, errorCode);
    274         } else if (uprv_strcmp(key, "per") == 0) {
    275             // For example, "{0}/h".
    276             setFormatterIfAbsent(PER_UNIT_INDEX, value, 1, errorCode);
    277         } else {
    278             // The key must be one of the plural form strings. For example:
    279             // one{"{0} hr"}
    280             // other{"{0} hrs"}
    281             setFormatterIfAbsent(StandardPlural::indexFromString(key, errorCode), value, 0,
    282                                     errorCode);
    283         }
    284     }
    285 
    286     /**
    287      * Consume a table of per-unit tables. For example,
    288      * unitsShort/duration contains tables for duration-unit subtypes day & hour.
    289      */
    290     void consumeSubtypeTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
    291         if (U_FAILURE(errorCode)) { return; }
    292         unitIndex = MeasureUnit::internalGetIndexForTypeAndSubtype(type, key);
    293         if (unitIndex < 0) {
    294             // TODO: How to handle unexpected data?
    295             // See http://bugs.icu-project.org/trac/ticket/12597
    296             return;
    297         }
    298 
    299         // We no longer handle units like "coordinate" here (which do not have plural variants)
    300         if (value.getType() == URES_TABLE) {
    301             // Units that have plural variants
    302             ResourceTable patternTableTable = value.getTable(errorCode);
    303             if (U_FAILURE(errorCode)) { return; }
    304             for (int i = 0; patternTableTable.getKeyAndValue(i, key, value); ++i) {
    305                 consumePattern(key, value, errorCode);
    306             }
    307         } else {
    308             // TODO: How to handle unexpected data?
    309             // See http://bugs.icu-project.org/trac/ticket/12597
    310             return;
    311         }
    312     }
    313 
    314     /**
    315      * Consume compound x-per-y display pattern. For example,
    316      * unitsShort/compound/per may be "{0}/{1}".
    317      */
    318     void consumeCompoundPattern(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
    319         if (U_SUCCESS(errorCode) && uprv_strcmp(key, "per") == 0) {
    320             cacheData.perFormatters[width].
    321                     applyPatternMinMaxArguments(value.getUnicodeString(errorCode), 2, 2, errorCode);
    322         }
    323     }
    324 
    325     /**
    326      * Consume a table of unit type tables. For example,
    327      * unitsShort contains tables for area & duration.
    328      * It also contains a table for the compound/per pattern.
    329      */
    330     void consumeUnitTypesTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
    331         if (U_FAILURE(errorCode)) { return; }
    332         if (uprv_strcmp(key, "currency") == 0) {
    333             // Skip.
    334         } else if (uprv_strcmp(key, "compound") == 0) {
    335             if (!cacheData.hasPerFormatter(width)) {
    336                 ResourceTable compoundTable = value.getTable(errorCode);
    337                 if (U_FAILURE(errorCode)) { return; }
    338                 for (int i = 0; compoundTable.getKeyAndValue(i, key, value); ++i) {
    339                     consumeCompoundPattern(key, value, errorCode);
    340                 }
    341             }
    342         } else if (uprv_strcmp(key, "coordinate") == 0) {
    343             // special handling but we need to determine what that is
    344         } else {
    345             type = key;
    346             ResourceTable subtypeTable = value.getTable(errorCode);
    347             if (U_FAILURE(errorCode)) { return; }
    348             for (int i = 0; subtypeTable.getKeyAndValue(i, key, value); ++i) {
    349                 consumeSubtypeTable(key, value, errorCode);
    350             }
    351         }
    352     }
    353 
    354     void consumeAlias(const char *key, const ResourceValue &value, UErrorCode &errorCode) {
    355         // Handle aliases like
    356         // units:alias{"/LOCALE/unitsShort"}
    357         // which should only occur in the root bundle.
    358         UMeasureFormatWidth sourceWidth = widthFromKey(key);
    359         if (sourceWidth == UMEASFMT_WIDTH_COUNT) {
    360             // Alias from something we don't care about.
    361             return;
    362         }
    363         UMeasureFormatWidth targetWidth = widthFromAlias(value, errorCode);
    364         if (targetWidth == UMEASFMT_WIDTH_COUNT) {
    365             // We do not recognize what to fall back to.
    366             errorCode = U_INVALID_FORMAT_ERROR;
    367             return;
    368         }
    369         // Check that we do not fall back to another fallback.
    370         if (cacheData.widthFallback[targetWidth] != UMEASFMT_WIDTH_COUNT) {
    371             errorCode = U_INVALID_FORMAT_ERROR;
    372             return;
    373         }
    374         cacheData.widthFallback[sourceWidth] = targetWidth;
    375     }
    376 
    377     void consumeTable(const char *key, ResourceValue &value, UErrorCode &errorCode) {
    378         if (U_SUCCESS(errorCode) && (width = widthFromKey(key)) != UMEASFMT_WIDTH_COUNT) {
    379             ResourceTable unitTypesTable = value.getTable(errorCode);
    380             if (U_FAILURE(errorCode)) { return; }
    381             for (int i = 0; unitTypesTable.getKeyAndValue(i, key, value); ++i) {
    382                 consumeUnitTypesTable(key, value, errorCode);
    383             }
    384         }
    385     }
    386 
    387     static UMeasureFormatWidth widthFromKey(const char *key) {
    388         if (uprv_strncmp(key, "units", 5) == 0) {
    389             key += 5;
    390             if (*key == 0) {
    391                 return UMEASFMT_WIDTH_WIDE;
    392             } else if (uprv_strcmp(key, "Short") == 0) {
    393                 return UMEASFMT_WIDTH_SHORT;
    394             } else if (uprv_strcmp(key, "Narrow") == 0) {
    395                 return UMEASFMT_WIDTH_NARROW;
    396             }
    397         }
    398         return UMEASFMT_WIDTH_COUNT;
    399     }
    400 
    401     static UMeasureFormatWidth widthFromAlias(const ResourceValue &value, UErrorCode &errorCode) {
    402         int32_t length;
    403         const UChar *s = value.getAliasString(length, errorCode);
    404         // For example: "/LOCALE/unitsShort"
    405         if (U_SUCCESS(errorCode) && length >= 13 && u_memcmp(s, g_LOCALE_units, 13) == 0) {
    406             s += 13;
    407             length -= 13;
    408             if (*s == 0) {
    409                 return UMEASFMT_WIDTH_WIDE;
    410             } else if (u_strCompare(s, length, gShort, 5, FALSE) == 0) {
    411                 return UMEASFMT_WIDTH_SHORT;
    412             } else if (u_strCompare(s, length, gNarrow, 6, FALSE) == 0) {
    413                 return UMEASFMT_WIDTH_NARROW;
    414             }
    415         }
    416         return UMEASFMT_WIDTH_COUNT;
    417     }
    418 
    419     virtual void put(const char *key, ResourceValue &value, UBool /*noFallback*/,
    420             UErrorCode &errorCode) {
    421         // Main entry point to sink
    422         ResourceTable widthsTable = value.getTable(errorCode);
    423         if (U_FAILURE(errorCode)) { return; }
    424         for (int i = 0; widthsTable.getKeyAndValue(i, key, value); ++i) {
    425             if (value.getType() == URES_ALIAS) {
    426                 consumeAlias(key, value, errorCode);
    427             } else {
    428                 consumeTable(key, value, errorCode);
    429             }
    430         }
    431     }
    432 };
    433 
    434 // Virtual destructors must be defined out of line.
    435 UnitDataSink::~UnitDataSink() {}
    436 
    437 }  // namespace
    438 
    439 static UBool loadMeasureUnitData(
    440         const UResourceBundle *resource,
    441         MeasureFormatCacheData &cacheData,
    442         UErrorCode &status) {
    443     UnitDataSink sink(cacheData);
    444     ures_getAllItemsWithFallback(resource, "", sink, status);
    445     return U_SUCCESS(status);
    446 }
    447 
    448 static UnicodeString loadNumericDateFormatterPattern(
    449         const UResourceBundle *resource,
    450         const char *pattern,
    451         UErrorCode &status) {
    452     UnicodeString result;
    453     if (U_FAILURE(status)) {
    454         return result;
    455     }
    456     CharString chs;
    457     chs.append("durationUnits", status)
    458             .append("/", status).append(pattern, status);
    459     LocalUResourceBundlePointer patternBundle(
    460             ures_getByKeyWithFallback(
    461                 resource,
    462                 chs.data(),
    463                 NULL,
    464                 &status));
    465     if (U_FAILURE(status)) {
    466         return result;
    467     }
    468     getString(patternBundle.getAlias(), result, status);
    469     // Replace 'h' with 'H'
    470     int32_t len = result.length();
    471     UChar *buffer = result.getBuffer(len);
    472     for (int32_t i = 0; i < len; ++i) {
    473         if (buffer[i] == 0x68) { // 'h'
    474             buffer[i] = 0x48; // 'H'
    475         }
    476     }
    477     result.releaseBuffer(len);
    478     return result;
    479 }
    480 
    481 static NumericDateFormatters *loadNumericDateFormatters(
    482         const UResourceBundle *resource,
    483         UErrorCode &status) {
    484     if (U_FAILURE(status)) {
    485         return NULL;
    486     }
    487     NumericDateFormatters *result = new NumericDateFormatters(
    488         loadNumericDateFormatterPattern(resource, "hm", status),
    489         loadNumericDateFormatterPattern(resource, "ms", status),
    490         loadNumericDateFormatterPattern(resource, "hms", status),
    491         status);
    492     if (U_FAILURE(status)) {
    493         delete result;
    494         return NULL;
    495     }
    496     return result;
    497 }
    498 
    499 template<> U_I18N_API
    500 const MeasureFormatCacheData *LocaleCacheKey<MeasureFormatCacheData>::createObject(
    501         const void * /*unused*/, UErrorCode &status) const {
    502     const char *localeId = fLoc.getName();
    503     LocalUResourceBundlePointer unitsBundle(ures_open(U_ICUDATA_UNIT, localeId, &status));
    504     static UNumberFormatStyle currencyStyles[] = {
    505             UNUM_CURRENCY_PLURAL, UNUM_CURRENCY_ISO, UNUM_CURRENCY};
    506     LocalPointer<MeasureFormatCacheData> result(new MeasureFormatCacheData(), status);
    507     if (U_FAILURE(status)) {
    508         return NULL;
    509     }
    510     if (!loadMeasureUnitData(
    511             unitsBundle.getAlias(),
    512             *result,
    513             status)) {
    514         return NULL;
    515     }
    516     result->adoptNumericDateFormatters(loadNumericDateFormatters(
    517             unitsBundle.getAlias(), status));
    518     if (U_FAILURE(status)) {
    519         return NULL;
    520     }
    521 
    522     for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) {
    523         // NumberFormat::createInstance can erase warning codes from status, so pass it
    524         // a separate status instance
    525         UErrorCode localStatus = U_ZERO_ERROR;
    526         result->adoptCurrencyFormat(i, NumberFormat::createInstance(
    527                 localeId, currencyStyles[i], localStatus));
    528         if (localStatus != U_ZERO_ERROR) {
    529             status = localStatus;
    530         }
    531         if (U_FAILURE(status)) {
    532             return NULL;
    533         }
    534     }
    535     NumberFormat *inf = NumberFormat::createInstance(
    536             localeId, UNUM_DECIMAL, status);
    537     if (U_FAILURE(status)) {
    538         return NULL;
    539     }
    540     inf->setMaximumFractionDigits(0);
    541     DecimalFormat *decfmt = dynamic_cast<DecimalFormat *>(inf);
    542     if (decfmt != NULL) {
    543         decfmt->setRoundingMode(DecimalFormat::kRoundDown);
    544     }
    545     result->adoptIntegerFormat(inf);
    546     result->addRef();
    547     return result.orphan();
    548 }
    549 
    550 static UBool isTimeUnit(const MeasureUnit &mu, const char *tu) {
    551     return uprv_strcmp(mu.getType(), "duration") == 0 &&
    552             uprv_strcmp(mu.getSubtype(), tu) == 0;
    553 }
    554 
    555 // Converts a composite measure into hours-minutes-seconds and stores at hms
    556 // array. [0] is hours; [1] is minutes; [2] is seconds. Returns a bit map of
    557 // units found: 1=hours, 2=minutes, 4=seconds. For example, if measures
    558 // contains hours-minutes, this function would return 3.
    559 //
    560 // If measures cannot be converted into hours, minutes, seconds or if amounts
    561 // are negative, or if hours, minutes, seconds are out of order, returns 0.
    562 static int32_t toHMS(
    563         const Measure *measures,
    564         int32_t measureCount,
    565         Formattable *hms,
    566         UErrorCode &status) {
    567     if (U_FAILURE(status)) {
    568         return 0;
    569     }
    570     int32_t result = 0;
    571     if (U_FAILURE(status)) {
    572         return 0;
    573     }
    574     // We use copy constructor to ensure that both sides of equality operator
    575     // are instances of MeasureUnit base class and not a subclass. Otherwise,
    576     // operator== will immediately return false.
    577     for (int32_t i = 0; i < measureCount; ++i) {
    578         if (isTimeUnit(measures[i].getUnit(), "hour")) {
    579             // hour must come first
    580             if (result >= 1) {
    581                 return 0;
    582             }
    583             hms[0] = measures[i].getNumber();
    584             if (hms[0].getDouble() < 0.0) {
    585                 return 0;
    586             }
    587             result |= 1;
    588         } else if (isTimeUnit(measures[i].getUnit(), "minute")) {
    589             // minute must come after hour
    590             if (result >= 2) {
    591                 return 0;
    592             }
    593             hms[1] = measures[i].getNumber();
    594             if (hms[1].getDouble() < 0.0) {
    595                 return 0;
    596             }
    597             result |= 2;
    598         } else if (isTimeUnit(measures[i].getUnit(), "second")) {
    599             // second must come after hour and minute
    600             if (result >= 4) {
    601                 return 0;
    602             }
    603             hms[2] = measures[i].getNumber();
    604             if (hms[2].getDouble() < 0.0) {
    605                 return 0;
    606             }
    607             result |= 4;
    608         } else {
    609             return 0;
    610         }
    611     }
    612     return result;
    613 }
    614 
    615 
    616 MeasureFormat::MeasureFormat(
    617         const Locale &locale, UMeasureFormatWidth w, UErrorCode &status)
    618         : cache(NULL),
    619           numberFormat(NULL),
    620           pluralRules(NULL),
    621           width(w),
    622           listFormatter(NULL) {
    623     initMeasureFormat(locale, w, NULL, status);
    624 }
    625 
    626 MeasureFormat::MeasureFormat(
    627         const Locale &locale,
    628         UMeasureFormatWidth w,
    629         NumberFormat *nfToAdopt,
    630         UErrorCode &status)
    631         : cache(NULL),
    632           numberFormat(NULL),
    633           pluralRules(NULL),
    634           width(w),
    635           listFormatter(NULL) {
    636     initMeasureFormat(locale, w, nfToAdopt, status);
    637 }
    638 
    639 MeasureFormat::MeasureFormat(const MeasureFormat &other) :
    640         Format(other),
    641         cache(other.cache),
    642         numberFormat(other.numberFormat),
    643         pluralRules(other.pluralRules),
    644         width(other.width),
    645         listFormatter(NULL) {
    646     cache->addRef();
    647     numberFormat->addRef();
    648     pluralRules->addRef();
    649     if (other.listFormatter != NULL) {
    650         listFormatter = new ListFormatter(*other.listFormatter);
    651     }
    652 }
    653 
    654 MeasureFormat &MeasureFormat::operator=(const MeasureFormat &other) {
    655     if (this == &other) {
    656         return *this;
    657     }
    658     Format::operator=(other);
    659     SharedObject::copyPtr(other.cache, cache);
    660     SharedObject::copyPtr(other.numberFormat, numberFormat);
    661     SharedObject::copyPtr(other.pluralRules, pluralRules);
    662     width = other.width;
    663     delete listFormatter;
    664     if (other.listFormatter != NULL) {
    665         listFormatter = new ListFormatter(*other.listFormatter);
    666     } else {
    667         listFormatter = NULL;
    668     }
    669     return *this;
    670 }
    671 
    672 MeasureFormat::MeasureFormat() :
    673         cache(NULL),
    674         numberFormat(NULL),
    675         pluralRules(NULL),
    676         width(UMEASFMT_WIDTH_SHORT),
    677         listFormatter(NULL) {
    678 }
    679 
    680 MeasureFormat::~MeasureFormat() {
    681     if (cache != NULL) {
    682         cache->removeRef();
    683     }
    684     if (numberFormat != NULL) {
    685         numberFormat->removeRef();
    686     }
    687     if (pluralRules != NULL) {
    688         pluralRules->removeRef();
    689     }
    690     delete listFormatter;
    691 }
    692 
    693 UBool MeasureFormat::operator==(const Format &other) const {
    694     if (this == &other) { // Same object, equal
    695         return TRUE;
    696     }
    697     if (!Format::operator==(other)) {
    698         return FALSE;
    699     }
    700     const MeasureFormat &rhs = static_cast<const MeasureFormat &>(other);
    701 
    702     // Note: Since the ListFormatter depends only on Locale and width, we
    703     // don't have to check it here.
    704 
    705     // differing widths aren't equivalent
    706     if (width != rhs.width) {
    707         return FALSE;
    708     }
    709     // Width the same check locales.
    710     // We don't need to check locales if both objects have same cache.
    711     if (cache != rhs.cache) {
    712         UErrorCode status = U_ZERO_ERROR;
    713         const char *localeId = getLocaleID(status);
    714         const char *rhsLocaleId = rhs.getLocaleID(status);
    715         if (U_FAILURE(status)) {
    716             // On failure, assume not equal
    717             return FALSE;
    718         }
    719         if (uprv_strcmp(localeId, rhsLocaleId) != 0) {
    720             return FALSE;
    721         }
    722     }
    723     // Locales same, check NumberFormat if shared data differs.
    724     return (
    725             numberFormat == rhs.numberFormat ||
    726             **numberFormat == **rhs.numberFormat);
    727 }
    728 
    729 Format *MeasureFormat::clone() const {
    730     return new MeasureFormat(*this);
    731 }
    732 
    733 UnicodeString &MeasureFormat::format(
    734         const Formattable &obj,
    735         UnicodeString &appendTo,
    736         FieldPosition &pos,
    737         UErrorCode &status) const {
    738     if (U_FAILURE(status)) return appendTo;
    739     if (obj.getType() == Formattable::kObject) {
    740         const UObject* formatObj = obj.getObject();
    741         const Measure* amount = dynamic_cast<const Measure*>(formatObj);
    742         if (amount != NULL) {
    743             return formatMeasure(
    744                     *amount, **numberFormat, appendTo, pos, status);
    745         }
    746     }
    747     status = U_ILLEGAL_ARGUMENT_ERROR;
    748     return appendTo;
    749 }
    750 
    751 void MeasureFormat::parseObject(
    752         const UnicodeString & /*source*/,
    753         Formattable & /*result*/,
    754         ParsePosition& /*pos*/) const {
    755     return;
    756 }
    757 
    758 UnicodeString &MeasureFormat::formatMeasurePerUnit(
    759         const Measure &measure,
    760         const MeasureUnit &perUnit,
    761         UnicodeString &appendTo,
    762         FieldPosition &pos,
    763         UErrorCode &status) const {
    764     if (U_FAILURE(status)) {
    765         return appendTo;
    766     }
    767     MeasureUnit *resolvedUnit =
    768             MeasureUnit::resolveUnitPerUnit(measure.getUnit(), perUnit);
    769     if (resolvedUnit != NULL) {
    770         Measure newMeasure(measure.getNumber(), resolvedUnit, status);
    771         return formatMeasure(
    772                 newMeasure, **numberFormat, appendTo, pos, status);
    773     }
    774     FieldPosition fpos(pos.getField());
    775     UnicodeString result;
    776     int32_t offset = withPerUnitAndAppend(
    777             formatMeasure(
    778                     measure, **numberFormat, result, fpos, status),
    779             perUnit,
    780             appendTo,
    781             status);
    782     if (U_FAILURE(status)) {
    783         return appendTo;
    784     }
    785     if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
    786         pos.setBeginIndex(fpos.getBeginIndex() + offset);
    787         pos.setEndIndex(fpos.getEndIndex() + offset);
    788     }
    789     return appendTo;
    790 }
    791 
    792 UnicodeString &MeasureFormat::formatMeasures(
    793         const Measure *measures,
    794         int32_t measureCount,
    795         UnicodeString &appendTo,
    796         FieldPosition &pos,
    797         UErrorCode &status) const {
    798     if (U_FAILURE(status)) {
    799         return appendTo;
    800     }
    801     if (measureCount == 0) {
    802         return appendTo;
    803     }
    804     if (measureCount == 1) {
    805         return formatMeasure(measures[0], **numberFormat, appendTo, pos, status);
    806     }
    807     if (width == UMEASFMT_WIDTH_NUMERIC) {
    808         Formattable hms[3];
    809         int32_t bitMap = toHMS(measures, measureCount, hms, status);
    810         if (bitMap > 0) {
    811             return formatNumeric(hms, bitMap, appendTo, status);
    812         }
    813     }
    814     if (pos.getField() != FieldPosition::DONT_CARE) {
    815         return formatMeasuresSlowTrack(
    816                 measures, measureCount, appendTo, pos, status);
    817     }
    818     UnicodeString *results = new UnicodeString[measureCount];
    819     if (results == NULL) {
    820         status = U_MEMORY_ALLOCATION_ERROR;
    821         return appendTo;
    822     }
    823     for (int32_t i = 0; i < measureCount; ++i) {
    824         const NumberFormat *nf = cache->getIntegerFormat();
    825         if (i == measureCount - 1) {
    826             nf = numberFormat->get();
    827         }
    828         formatMeasure(
    829                 measures[i],
    830                 *nf,
    831                 results[i],
    832                 pos,
    833                 status);
    834     }
    835     listFormatter->format(results, measureCount, appendTo, status);
    836     delete [] results;
    837     return appendTo;
    838 }
    839 
    840 UnicodeString MeasureFormat::getUnitDisplayName(const MeasureUnit& unit, UErrorCode& /*status*/) const {
    841     UMeasureFormatWidth width = getRegularWidth(this->width);
    842     const UChar* const* styleToDnam = cache->dnams[unit.getIndex()];
    843     const UChar* dnam = styleToDnam[width];
    844     if (dnam == NULL) {
    845         int32_t fallbackWidth = cache->widthFallback[width];
    846         dnam = styleToDnam[fallbackWidth];
    847     }
    848 
    849     UnicodeString result;
    850     if (dnam == NULL) {
    851         result.setToBogus();
    852     } else {
    853         result.setTo(dnam, -1);
    854     }
    855     return result;
    856 }
    857 
    858 void MeasureFormat::initMeasureFormat(
    859         const Locale &locale,
    860         UMeasureFormatWidth w,
    861         NumberFormat *nfToAdopt,
    862         UErrorCode &status) {
    863     static const char *listStyles[] = {"unit", "unit-short", "unit-narrow"};
    864     LocalPointer<NumberFormat> nf(nfToAdopt);
    865     if (U_FAILURE(status)) {
    866         return;
    867     }
    868     const char *name = locale.getName();
    869     setLocaleIDs(name, name);
    870 
    871     UnifiedCache::getByLocale(locale, cache, status);
    872     if (U_FAILURE(status)) {
    873         return;
    874     }
    875 
    876     const SharedPluralRules *pr = PluralRules::createSharedInstance(
    877             locale, UPLURAL_TYPE_CARDINAL, status);
    878     if (U_FAILURE(status)) {
    879         return;
    880     }
    881     SharedObject::copyPtr(pr, pluralRules);
    882     pr->removeRef();
    883     if (nf.isNull()) {
    884         const SharedNumberFormat *shared = NumberFormat::createSharedInstance(
    885                 locale, UNUM_DECIMAL, status);
    886         if (U_FAILURE(status)) {
    887             return;
    888         }
    889         SharedObject::copyPtr(shared, numberFormat);
    890         shared->removeRef();
    891     } else {
    892         adoptNumberFormat(nf.orphan(), status);
    893         if (U_FAILURE(status)) {
    894             return;
    895         }
    896     }
    897     width = w;
    898     delete listFormatter;
    899     listFormatter = ListFormatter::createInstance(
    900             locale,
    901             listStyles[getRegularWidth(width)],
    902             status);
    903 }
    904 
    905 void MeasureFormat::adoptNumberFormat(
    906         NumberFormat *nfToAdopt, UErrorCode &status) {
    907     LocalPointer<NumberFormat> nf(nfToAdopt);
    908     if (U_FAILURE(status)) {
    909         return;
    910     }
    911     SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias());
    912     if (shared == NULL) {
    913         status = U_MEMORY_ALLOCATION_ERROR;
    914         return;
    915     }
    916     nf.orphan();
    917     SharedObject::copyPtr(shared, numberFormat);
    918 }
    919 
    920 UBool MeasureFormat::setMeasureFormatLocale(const Locale &locale, UErrorCode &status) {
    921     if (U_FAILURE(status) || locale == getLocale(status)) {
    922         return FALSE;
    923     }
    924     initMeasureFormat(locale, width, NULL, status);
    925     return U_SUCCESS(status);
    926 }
    927 
    928 const NumberFormat &MeasureFormat::getNumberFormat() const {
    929     return **numberFormat;
    930 }
    931 
    932 const PluralRules &MeasureFormat::getPluralRules() const {
    933     return **pluralRules;
    934 }
    935 
    936 Locale MeasureFormat::getLocale(UErrorCode &status) const {
    937     return Format::getLocale(ULOC_VALID_LOCALE, status);
    938 }
    939 
    940 const char *MeasureFormat::getLocaleID(UErrorCode &status) const {
    941     return Format::getLocaleID(ULOC_VALID_LOCALE, status);
    942 }
    943 
    944 UnicodeString &MeasureFormat::formatMeasure(
    945         const Measure &measure,
    946         const NumberFormat &nf,
    947         UnicodeString &appendTo,
    948         FieldPosition &pos,
    949         UErrorCode &status) const {
    950     if (U_FAILURE(status)) {
    951         return appendTo;
    952     }
    953     const Formattable& amtNumber = measure.getNumber();
    954     const MeasureUnit& amtUnit = measure.getUnit();
    955     if (isCurrency(amtUnit)) {
    956         UChar isoCode[4];
    957         u_charsToUChars(amtUnit.getSubtype(), isoCode, 4);
    958         return cache->getCurrencyFormat(width)->format(
    959                 new CurrencyAmount(amtNumber, isoCode, status),
    960                 appendTo,
    961                 pos,
    962                 status);
    963     }
    964     UnicodeString formattedNumber;
    965     StandardPlural::Form pluralForm = QuantityFormatter::selectPlural(
    966             amtNumber, nf, **pluralRules, formattedNumber, pos, status);
    967     const SimpleFormatter *formatter = getPluralFormatter(amtUnit, width, pluralForm, status);
    968     return QuantityFormatter::format(*formatter, formattedNumber, appendTo, pos, status);
    969 }
    970 
    971 // Formats hours-minutes-seconds as 5:37:23 or similar.
    972 UnicodeString &MeasureFormat::formatNumeric(
    973         const Formattable *hms,  // always length 3
    974         int32_t bitMap,   // 1=hourset, 2=minuteset, 4=secondset
    975         UnicodeString &appendTo,
    976         UErrorCode &status) const {
    977     if (U_FAILURE(status)) {
    978         return appendTo;
    979     }
    980     UDate millis =
    981         (UDate) (((uprv_trunc(hms[0].getDouble(status)) * 60.0
    982              + uprv_trunc(hms[1].getDouble(status))) * 60.0
    983                   + uprv_trunc(hms[2].getDouble(status))) * 1000.0);
    984     switch (bitMap) {
    985     case 5: // hs
    986     case 7: // hms
    987         return formatNumeric(
    988                 millis,
    989                 cache->getNumericDateFormatters()->hourMinuteSecond,
    990                 UDAT_SECOND_FIELD,
    991                 hms[2],
    992                 appendTo,
    993                 status);
    994         break;
    995     case 6: // ms
    996         return formatNumeric(
    997                 millis,
    998                 cache->getNumericDateFormatters()->minuteSecond,
    999                 UDAT_SECOND_FIELD,
   1000                 hms[2],
   1001                 appendTo,
   1002                 status);
   1003         break;
   1004     case 3: // hm
   1005         return formatNumeric(
   1006                 millis,
   1007                 cache->getNumericDateFormatters()->hourMinute,
   1008                 UDAT_MINUTE_FIELD,
   1009                 hms[1],
   1010                 appendTo,
   1011                 status);
   1012         break;
   1013     default:
   1014         status = U_INTERNAL_PROGRAM_ERROR;
   1015         return appendTo;
   1016         break;
   1017     }
   1018     return appendTo;
   1019 }
   1020 
   1021 static void appendRange(
   1022         const UnicodeString &src,
   1023         int32_t start,
   1024         int32_t end,
   1025         UnicodeString &dest) {
   1026     dest.append(src, start, end - start);
   1027 }
   1028 
   1029 static void appendRange(
   1030         const UnicodeString &src,
   1031         int32_t end,
   1032         UnicodeString &dest) {
   1033     dest.append(src, end, src.length() - end);
   1034 }
   1035 
   1036 // Formats time like 5:37:23
   1037 UnicodeString &MeasureFormat::formatNumeric(
   1038         UDate date, // Time since epoch 1:30:00 would be 5400000
   1039         const DateFormat &dateFmt, // h:mm, m:ss, or h:mm:ss
   1040         UDateFormatField smallestField, // seconds in 5:37:23.5
   1041         const Formattable &smallestAmount, // 23.5 for 5:37:23.5
   1042         UnicodeString &appendTo,
   1043         UErrorCode &status) const {
   1044     if (U_FAILURE(status)) {
   1045         return appendTo;
   1046     }
   1047     // Format the smallest amount with this object's NumberFormat
   1048     UnicodeString smallestAmountFormatted;
   1049 
   1050     // We keep track of the integer part of smallest amount so that
   1051     // we can replace it later so that we get '0:00:09.3' instead of
   1052     // '0:00:9.3'
   1053     FieldPosition intFieldPosition(UNUM_INTEGER_FIELD);
   1054     (*numberFormat)->format(
   1055             smallestAmount, smallestAmountFormatted, intFieldPosition, status);
   1056     if (
   1057             intFieldPosition.getBeginIndex() == 0 &&
   1058             intFieldPosition.getEndIndex() == 0) {
   1059         status = U_INTERNAL_PROGRAM_ERROR;
   1060         return appendTo;
   1061     }
   1062 
   1063     // Format time. draft becomes something like '5:30:45'
   1064     FieldPosition smallestFieldPosition(smallestField);
   1065     UnicodeString draft;
   1066     dateFmt.format(date, draft, smallestFieldPosition, status);
   1067 
   1068     // If we find field for smallest amount replace it with the formatted
   1069     // smallest amount from above taking care to replace the integer part
   1070     // with what is in original time. For example, If smallest amount
   1071     // is 9.35s and the formatted time is 0:00:09 then 9.35 becomes 09.35
   1072     // and replacing yields 0:00:09.35
   1073     if (smallestFieldPosition.getBeginIndex() != 0 ||
   1074             smallestFieldPosition.getEndIndex() != 0) {
   1075         appendRange(draft, 0, smallestFieldPosition.getBeginIndex(), appendTo);
   1076         appendRange(
   1077                 smallestAmountFormatted,
   1078                 0,
   1079                 intFieldPosition.getBeginIndex(),
   1080                 appendTo);
   1081         appendRange(
   1082                 draft,
   1083                 smallestFieldPosition.getBeginIndex(),
   1084                 smallestFieldPosition.getEndIndex(),
   1085                 appendTo);
   1086         appendRange(
   1087                 smallestAmountFormatted,
   1088                 intFieldPosition.getEndIndex(),
   1089                 appendTo);
   1090         appendRange(
   1091                 draft,
   1092                 smallestFieldPosition.getEndIndex(),
   1093                 appendTo);
   1094     } else {
   1095         appendTo.append(draft);
   1096     }
   1097     return appendTo;
   1098 }
   1099 
   1100 const SimpleFormatter *MeasureFormat::getFormatterOrNull(
   1101         const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index) const {
   1102     width = getRegularWidth(width);
   1103     SimpleFormatter *const (*unitPatterns)[PATTERN_COUNT] = &cache->patterns[unit.getIndex()][0];
   1104     if (unitPatterns[width][index] != NULL) {
   1105         return unitPatterns[width][index];
   1106     }
   1107     int32_t fallbackWidth = cache->widthFallback[width];
   1108     if (fallbackWidth != UMEASFMT_WIDTH_COUNT && unitPatterns[fallbackWidth][index] != NULL) {
   1109         return unitPatterns[fallbackWidth][index];
   1110     }
   1111     return NULL;
   1112 }
   1113 
   1114 const SimpleFormatter *MeasureFormat::getFormatter(
   1115         const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
   1116         UErrorCode &errorCode) const {
   1117     if (U_FAILURE(errorCode)) {
   1118         return NULL;
   1119     }
   1120     const SimpleFormatter *pattern = getFormatterOrNull(unit, width, index);
   1121     if (pattern == NULL) {
   1122         errorCode = U_MISSING_RESOURCE_ERROR;
   1123     }
   1124     return pattern;
   1125 }
   1126 
   1127 const SimpleFormatter *MeasureFormat::getPluralFormatter(
   1128         const MeasureUnit &unit, UMeasureFormatWidth width, int32_t index,
   1129         UErrorCode &errorCode) const {
   1130     if (U_FAILURE(errorCode)) {
   1131         return NULL;
   1132     }
   1133     if (index != StandardPlural::OTHER) {
   1134         const SimpleFormatter *pattern = getFormatterOrNull(unit, width, index);
   1135         if (pattern != NULL) {
   1136             return pattern;
   1137         }
   1138     }
   1139     return getFormatter(unit, width, StandardPlural::OTHER, errorCode);
   1140 }
   1141 
   1142 const SimpleFormatter *MeasureFormat::getPerFormatter(
   1143         UMeasureFormatWidth width,
   1144         UErrorCode &status) const {
   1145     if (U_FAILURE(status)) {
   1146         return NULL;
   1147     }
   1148     width = getRegularWidth(width);
   1149     const SimpleFormatter * perFormatters = cache->perFormatters;
   1150     if (perFormatters[width].getArgumentLimit() == 2) {
   1151         return &perFormatters[width];
   1152     }
   1153     int32_t fallbackWidth = cache->widthFallback[width];
   1154     if (fallbackWidth != UMEASFMT_WIDTH_COUNT &&
   1155             perFormatters[fallbackWidth].getArgumentLimit() == 2) {
   1156         return &perFormatters[fallbackWidth];
   1157     }
   1158     status = U_MISSING_RESOURCE_ERROR;
   1159     return NULL;
   1160 }
   1161 
   1162 int32_t MeasureFormat::withPerUnitAndAppend(
   1163         const UnicodeString &formatted,
   1164         const MeasureUnit &perUnit,
   1165         UnicodeString &appendTo,
   1166         UErrorCode &status) const {
   1167     int32_t offset = -1;
   1168     if (U_FAILURE(status)) {
   1169         return offset;
   1170     }
   1171     const SimpleFormatter *perUnitFormatter = getFormatterOrNull(perUnit, width, PER_UNIT_INDEX);
   1172     if (perUnitFormatter != NULL) {
   1173         const UnicodeString *params[] = {&formatted};
   1174         perUnitFormatter->formatAndAppend(
   1175                 params,
   1176                 UPRV_LENGTHOF(params),
   1177                 appendTo,
   1178                 &offset,
   1179                 1,
   1180                 status);
   1181         return offset;
   1182     }
   1183     const SimpleFormatter *perFormatter = getPerFormatter(width, status);
   1184     const SimpleFormatter *pattern =
   1185             getPluralFormatter(perUnit, width, StandardPlural::ONE, status);
   1186     if (U_FAILURE(status)) {
   1187         return offset;
   1188     }
   1189     UnicodeString perUnitString = pattern->getTextWithNoArguments();
   1190     perUnitString.trim();
   1191     const UnicodeString *params[] = {&formatted, &perUnitString};
   1192     perFormatter->formatAndAppend(
   1193             params,
   1194             UPRV_LENGTHOF(params),
   1195             appendTo,
   1196             &offset,
   1197             1,
   1198             status);
   1199     return offset;
   1200 }
   1201 
   1202 UnicodeString &MeasureFormat::formatMeasuresSlowTrack(
   1203         const Measure *measures,
   1204         int32_t measureCount,
   1205         UnicodeString& appendTo,
   1206         FieldPosition& pos,
   1207         UErrorCode& status) const {
   1208     if (U_FAILURE(status)) {
   1209         return appendTo;
   1210     }
   1211     FieldPosition dontCare(FieldPosition::DONT_CARE);
   1212     FieldPosition fpos(pos.getField());
   1213     UnicodeString *results = new UnicodeString[measureCount];
   1214     int32_t fieldPositionFoundIndex = -1;
   1215     for (int32_t i = 0; i < measureCount; ++i) {
   1216         const NumberFormat *nf = cache->getIntegerFormat();
   1217         if (i == measureCount - 1) {
   1218             nf = numberFormat->get();
   1219         }
   1220         if (fieldPositionFoundIndex == -1) {
   1221             formatMeasure(measures[i], *nf, results[i], fpos, status);
   1222             if (U_FAILURE(status)) {
   1223                 delete [] results;
   1224                 return appendTo;
   1225             }
   1226             if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) {
   1227                 fieldPositionFoundIndex = i;
   1228             }
   1229         } else {
   1230             formatMeasure(measures[i], *nf, results[i], dontCare, status);
   1231         }
   1232     }
   1233     int32_t offset;
   1234     listFormatter->format(
   1235             results,
   1236             measureCount,
   1237             appendTo,
   1238             fieldPositionFoundIndex,
   1239             offset,
   1240             status);
   1241     if (U_FAILURE(status)) {
   1242         delete [] results;
   1243         return appendTo;
   1244     }
   1245     if (offset != -1) {
   1246         pos.setBeginIndex(fpos.getBeginIndex() + offset);
   1247         pos.setEndIndex(fpos.getEndIndex() + offset);
   1248     }
   1249     delete [] results;
   1250     return appendTo;
   1251 }
   1252 
   1253 MeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(const Locale& locale,
   1254                                                    UErrorCode& ec) {
   1255     CurrencyFormat* fmt = NULL;
   1256     if (U_SUCCESS(ec)) {
   1257         fmt = new CurrencyFormat(locale, ec);
   1258         if (U_FAILURE(ec)) {
   1259             delete fmt;
   1260             fmt = NULL;
   1261         }
   1262     }
   1263     return fmt;
   1264 }
   1265 
   1266 MeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(UErrorCode& ec) {
   1267     if (U_FAILURE(ec)) {
   1268         return NULL;
   1269     }
   1270     return MeasureFormat::createCurrencyFormat(Locale::getDefault(), ec);
   1271 }
   1272 
   1273 U_NAMESPACE_END
   1274 
   1275 #endif /* #if !UCONFIG_NO_FORMATTING */
   1276