1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 3fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius* Copyright (c) 2004-2014, International Business Machines 4ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Corporation and others. All Rights Reserved. 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Author: Alan Liu 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Created: April 20, 2004 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru* Since: ICU 3.0 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru********************************************************************** 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru*/ 11fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "utypeinfo.h" // for 'typeid' to work 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/utypes.h" 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if !UCONFIG_NO_FORMATTING 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "unicode/measfmt.h" 17fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/numfmt.h" 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "currfmt.h" 19fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/localpointer.h" 20fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "quantityformatter.h" 21fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/plurrule.h" 22fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/decimfmt.h" 23fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "lrucache.h" 24fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "uresimp.h" 25fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/ures.h" 26fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "cstring.h" 27fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "mutex.h" 28fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "ucln_in.h" 29fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/listformatter.h" 30fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "charstr.h" 31fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/putil.h" 32fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "unicode/smpdtfmt.h" 33fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 34fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "sharednumberformat.h" 35fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#include "sharedpluralrules.h" 36fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 37fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define LENGTHOF(array) (int32_t)(sizeof(array)/sizeof((array)[0])) 38fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define MEAS_UNIT_COUNT 46 39fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius#define WIDTH_INDEX_COUNT (UMEASFMT_WIDTH_NARROW + 1) 40fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 41fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic icu::LRUCache *gCache = NULL; 42fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UMutex gCacheMutex = U_MUTEX_INITIALIZER; 43fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic icu::UInitOnce gCacheInitOnce = U_INITONCE_INITIALIZER; 44fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 45fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CDECL_BEGIN 46fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool U_CALLCONV measfmt_cleanup() { 47fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gCacheInitOnce.reset(); 48fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (gCache) { 49fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete gCache; 50fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gCache = NULL; 51fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 52fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 53fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 54fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusU_CDECL_END 55ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 58fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUOBJECT_DEFINE_RTTI_IMPLEMENTATION(MeasureFormat) 59fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 60fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Used to format durations like 5:47 or 21:35:42. 61fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass NumericDateFormatters : public UMemory { 62fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic: 63fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Formats like H:mm 64fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimpleDateFormat hourMinute; 65fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 66fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // formats like M:ss 67fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimpleDateFormat minuteSecond; 68fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 69fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // formats like H:mm:ss 70fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SimpleDateFormat hourMinuteSecond; 71fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 72fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Constructor that takes the actual patterns for hour-minute, 73fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // minute-second, and hour-minute-second respectively. 74fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumericDateFormatters( 75fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &hm, 76fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &ms, 77fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &hms, 78fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) : 79fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hourMinute(hm, status), 80fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius minuteSecond(ms, status), 81fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hourMinuteSecond(hms, status) { 82fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const TimeZone *gmt = TimeZone::getGMT(); 83fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hourMinute.setTimeZone(*gmt); 84fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius minuteSecond.setTimeZone(*gmt); 85fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hourMinuteSecond.setTimeZone(*gmt); 86fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 87fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate: 88fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumericDateFormatters(const NumericDateFormatters &other); 89fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumericDateFormatters &operator=(const NumericDateFormatters &other); 90fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 91fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 92fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Instances contain all MeasureFormat specific data for a particular locale. 93fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// This data is cached. It is never copied, but is shared via shared pointers. 94fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusclass MeasureFormatCacheData : public SharedObject { 95fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliuspublic: 96fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius QuantityFormatter formatters[MEAS_UNIT_COUNT][WIDTH_INDEX_COUNT]; 97fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius MeasureFormatCacheData(); 98fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void adoptCurrencyFormat(int32_t widthIndex, NumberFormat *nfToAdopt) { 99fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete currencyFormats[widthIndex]; 100fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius currencyFormats[widthIndex] = nfToAdopt; 101fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 102fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat *getCurrencyFormat(int32_t widthIndex) const { 103fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return currencyFormats[widthIndex]; 104fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 105fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void adoptIntegerFormat(NumberFormat *nfToAdopt) { 106fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete integerFormat; 107fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius integerFormat = nfToAdopt; 108fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 109fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat *getIntegerFormat() const { 110fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return integerFormat; 111fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 112fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius void adoptNumericDateFormatters(NumericDateFormatters *formattersToAdopt) { 113fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete numericDateFormatters; 114fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numericDateFormatters = formattersToAdopt; 115fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 116fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumericDateFormatters *getNumericDateFormatters() const { 117fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return numericDateFormatters; 118fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 119fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius virtual ~MeasureFormatCacheData(); 120fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusprivate: 121fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *currencyFormats[WIDTH_INDEX_COUNT]; 122fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *integerFormat; 123fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumericDateFormatters *numericDateFormatters; 124fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius MeasureFormatCacheData(const MeasureFormatCacheData &other); 125fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius MeasureFormatCacheData &operator=(const MeasureFormatCacheData &other); 126fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius}; 127fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 128fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormatCacheData::MeasureFormatCacheData() { 129fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < LENGTHOF(currencyFormats); ++i) { 130fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius currencyFormats[i] = NULL; 131fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 132fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius integerFormat = NULL; 133fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numericDateFormatters = NULL; 134fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 135fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 136fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormatCacheData::~MeasureFormatCacheData() { 137fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < LENGTHOF(currencyFormats); ++i) { 138fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete currencyFormats[i]; 139fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 140fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete integerFormat; 141fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete numericDateFormatters; 142fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 143fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 144fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t widthToIndex(UMeasureFormatWidth width) { 145fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (width >= WIDTH_INDEX_COUNT) { 146fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return WIDTH_INDEX_COUNT - 1; 147fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 148fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return width; 149fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 150fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 151fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool isCurrency(const MeasureUnit &unit) { 152fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return (uprv_strcmp(unit.getType(), "currency") == 0); 153fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 154fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 155fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool getString( 156fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UResourceBundle *resource, 157fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &result, 158fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 159fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t len = 0; 160fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UChar *resStr = ures_getString(resource, &len, &status); 161fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 162fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 163fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 164fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result.setTo(TRUE, resStr, len); 165fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 166fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 167fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 168fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 169fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool loadMeasureUnitData( 170fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UResourceBundle *resource, 171fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius MeasureFormatCacheData &cacheData, 172fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 173fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 174fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 175fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 176fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static const char *widthPath[] = {"units", "unitsShort", "unitsNarrow"}; 177fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius MeasureUnit *units = NULL; 178fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t unitCount = MeasureUnit::getAvailable(units, 0, status); 179fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius while (status == U_BUFFER_OVERFLOW_ERROR) { 180fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ZERO_ERROR; 181fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 182fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius units = new MeasureUnit[unitCount]; 183fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (units == NULL) { 184fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 185fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 186fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 187fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unitCount = MeasureUnit::getAvailable(units, unitCount, status); 188fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 189fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t currentWidth = 0; currentWidth < WIDTH_INDEX_COUNT; ++currentWidth) { 190fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Be sure status is clear since next resource bundle lookup may fail. 191fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 192fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 193fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 194fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 195fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer widthBundle( 196fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback( 197fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius resource, widthPath[currentWidth], NULL, &status)); 198fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We may not have data for all widths in all locales. 199fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (status == U_MISSING_RESOURCE_ERROR) { 200fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ZERO_ERROR; 201fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius continue; 202fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 203fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t currentUnit = 0; currentUnit < unitCount; ++currentUnit) { 204fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Be sure status is clear next lookup may fail. 205fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 206fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 207fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 208fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 209fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (isCurrency(units[currentUnit])) { 210fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius continue; 211fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 212fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius CharString pathBuffer; 213fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pathBuffer.append(units[currentUnit].getType(), status) 214fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius .append("/", status) 215fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius .append(units[currentUnit].getSubtype(), status); 216fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer unitBundle( 217fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback( 218fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius widthBundle.getAlias(), 219fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pathBuffer.data(), 220fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 221fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius &status)); 222fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We may not have data for all units in all widths 223fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (status == U_MISSING_RESOURCE_ERROR) { 224fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ZERO_ERROR; 225fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius continue; 226fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 227fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We must have the unit bundle to proceed 228fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 229fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 230fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 231fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 232fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t size = ures_getSize(unitBundle.getAlias()); 233fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t plIndex = 0; plIndex < size; ++plIndex) { 234fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer pluralBundle( 235fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByIndex( 236fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius unitBundle.getAlias(), plIndex, NULL, &status)); 237fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 238fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 239fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 240fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 241fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString rawPattern; 242fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius getString(pluralBundle.getAlias(), rawPattern, status); 243fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cacheData.formatters[units[currentUnit].getIndex()][currentWidth].add( 244fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getKey(pluralBundle.getAlias()), 245fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius rawPattern, 246fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 247fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 248fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 249fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 250fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] units; 251fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return U_SUCCESS(status); 252fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 253fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 254fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UnicodeString loadNumericDateFormatterPattern( 255fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UResourceBundle *resource, 256fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *pattern, 257fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 258fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString result; 259fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 260fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result; 261fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 262fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius CharString chs; 263fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius chs.append("durationUnits", status) 264fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius .append("/", status).append(pattern, status); 265fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer patternBundle( 266fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ures_getByKeyWithFallback( 267fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius resource, 268fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius chs.data(), 269fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NULL, 270fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius &status)); 271fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 272fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result; 273fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 274fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius getString(patternBundle.getAlias(), result, status); 275fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Replace 'h' with 'H' 276fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t len = result.length(); 277fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UChar *buffer = result.getBuffer(len); 278fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < len; ++i) { 279fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (buffer[i] == 0x68) { // 'h' 280fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius buffer[i] = 0x48; // 'H' 281fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 282fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 283fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result.releaseBuffer(len); 284fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result; 285fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 286ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 287fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic NumericDateFormatters *loadNumericDateFormatters( 288fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UResourceBundle *resource, 289fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 290fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 291fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 292fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 293fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumericDateFormatters *result = new NumericDateFormatters( 294fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius loadNumericDateFormatterPattern(resource, "hm", status), 295fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius loadNumericDateFormatterPattern(resource, "ms", status), 296fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius loadNumericDateFormatterPattern(resource, "hms", status), 297fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 298fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 299fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete result; 300fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 301fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 302fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result; 303fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 304fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 305fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Creates the MeasureFormatCacheData for a particular locale 306fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic SharedObject *U_CALLCONV createData( 307fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *localeId, UErrorCode &status) { 308fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalUResourceBundlePointer topLevel(ures_open(NULL, localeId, &status)); 309fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static UNumberFormatStyle currencyStyles[] = { 310fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UNUM_CURRENCY_PLURAL, UNUM_CURRENCY_ISO, UNUM_CURRENCY}; 311fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 312fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 313fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 314fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalPointer<MeasureFormatCacheData> result(new MeasureFormatCacheData()); 315fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (result.isNull()) { 316fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 317fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 318fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 319fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (!loadMeasureUnitData( 320fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius topLevel.getAlias(), 321fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *result, 322fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status)) { 323fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 324fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 325fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result->adoptNumericDateFormatters(loadNumericDateFormatters( 326fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius topLevel.getAlias(), status)); 327fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 328fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 329fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 330fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 331fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < WIDTH_INDEX_COUNT; ++i) { 332fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result->adoptCurrencyFormat(i, NumberFormat::createInstance( 333fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius localeId, currencyStyles[i], status)); 334fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 335fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 336fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 337fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 338fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *inf = NumberFormat::createInstance( 339fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius localeId, UNUM_DECIMAL, status); 340fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 341fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 342fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 343fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius inf->setMaximumFractionDigits(0); 344fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius DecimalFormat *decfmt = dynamic_cast<DecimalFormat *>(inf); 345fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (decfmt != NULL) { 346fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius decfmt->setRoundingMode(DecimalFormat::kRoundDown); 347fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 348fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result->adoptIntegerFormat(inf); 349fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result.orphan(); 350fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 351fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 352fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void U_CALLCONV cacheInit(UErrorCode &status) { 353fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(gCache == NULL); 354fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius U_ASSERT(MeasureUnit::getIndexCount() == MEAS_UNIT_COUNT); 355fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ucln_i18n_registerCleanup(UCLN_I18N_MEASFMT, measfmt_cleanup); 356fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gCache = new SimpleLRUCache(100, &createData, status); 357fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 358fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete gCache; 359fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gCache = NULL; 360fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 361fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 362fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 363fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool getFromCache( 364fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *locale, 365fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const MeasureFormatCacheData *&ptr, 366fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 367fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius umtx_initOnce(gCacheInitOnce, &cacheInit, status); 368fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 369fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 370fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 371fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Mutex lock(&gCacheMutex); 372fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius gCache->get(locale, ptr, status); 373fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return U_SUCCESS(status); 374fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 375fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 376fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic UBool isTimeUnit(const MeasureUnit &mu, const char *tu) { 377fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return uprv_strcmp(mu.getType(), "duration") == 0 && 378fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius uprv_strcmp(mu.getSubtype(), tu) == 0; 379fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 380fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 381fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Converts a composite measure into hours-minutes-seconds and stores at hms 382fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// array. [0] is hours; [1] is minutes; [2] is seconds. Returns a bit map of 383fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// units found: 1=hours, 2=minutes, 4=seconds. For example, if measures 384fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// contains hours-minutes, this function would return 3. 385fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// 386fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// If measures cannot be converted into hours, minutes, seconds or if amounts 387fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// are negative, or if hours, minutes, seconds are out of order, returns 0. 388fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic int32_t toHMS( 389fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Measure *measures, 390fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t measureCount, 391fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Formattable *hms, 392fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 393fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 394fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 395fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 396fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t result = 0; 397fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 398fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 399fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 400fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We use copy constructor to ensure that both sides of equality operator 401fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // are instances of MeasureUnit base class and not a subclass. Otherwise, 402fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // operator== will immediately return false. 403fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < measureCount; ++i) { 404fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (isTimeUnit(measures[i].getUnit(), "hour")) { 405fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // hour must come first 406fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (result >= 1) { 407fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 408fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 409fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[0] = measures[i].getNumber(); 410fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (hms[0].getDouble() < 0.0) { 411fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 412fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 413fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result |= 1; 414fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (isTimeUnit(measures[i].getUnit(), "minute")) { 415fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // minute must come after hour 416fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (result >= 2) { 417fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 418fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 419fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[1] = measures[i].getNumber(); 420fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (hms[1].getDouble() < 0.0) { 421fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 422fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 423fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result |= 2; 424fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else if (isTimeUnit(measures[i].getUnit(), "second")) { 425fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // second must come after hour and minute 426fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (result >= 4) { 427fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 428fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 429fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[2] = measures[i].getNumber(); 430fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (hms[2].getDouble() < 0.0) { 431fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 432fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 433fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius result |= 4; 434fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 435fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return 0; 436fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 437fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 438fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return result; 439fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 440fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 441fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 442fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat::MeasureFormat( 443fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Locale &locale, UMeasureFormatWidth w, UErrorCode &status) 444fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius : cache(NULL), 445fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat(NULL), 446fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules(NULL), 447fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width(w), 448fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter(NULL) { 449fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius initMeasureFormat(locale, w, NULL, status); 450fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 451fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 452fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat::MeasureFormat( 453fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Locale &locale, 454fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UMeasureFormatWidth w, 455fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *nfToAdopt, 456fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) 457fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius : cache(NULL), 458fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat(NULL), 459fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules(NULL), 460fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width(w), 461fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter(NULL) { 462fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius initMeasureFormat(locale, w, nfToAdopt, status); 463fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 464fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 465fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat::MeasureFormat(const MeasureFormat &other) : 466fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Format(other), 467fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache(other.cache), 468fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat(other.numberFormat), 469fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules(other.pluralRules), 470fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width(other.width), 471fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter(NULL) { 472fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->addRef(); 473fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat->addRef(); 474fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules->addRef(); 475fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter = new ListFormatter(*other.listFormatter); 476fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 477fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 478fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat &MeasureFormat::operator=(const MeasureFormat &other) { 479fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (this == &other) { 480fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 481fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 482fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Format::operator=(other); 483fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr(other.cache, cache); 484fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr(other.numberFormat, numberFormat); 485fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr(other.pluralRules, pluralRules); 486fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width = other.width; 487fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete listFormatter; 488fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter = new ListFormatter(*other.listFormatter); 489fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return *this; 490fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 491fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 492fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat::MeasureFormat() : 493fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache(NULL), 494fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat(NULL), 495fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules(NULL), 496fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width(UMEASFMT_WIDTH_WIDE), 497fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter(NULL) { 498fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 499fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 500fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusMeasureFormat::~MeasureFormat() { 501fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (cache != NULL) { 502fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->removeRef(); 503fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 504fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (numberFormat != NULL) { 505fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat->removeRef(); 506fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 507fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (pluralRules != NULL) { 508fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules->removeRef(); 509fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 510fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete listFormatter; 511fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 512fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 513fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool MeasureFormat::operator==(const Format &other) const { 514fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (this == &other) { // Same object, equal 515fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return TRUE; 516fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 517fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (!Format::operator==(other)) { 518fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 519fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 520fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const MeasureFormat &rhs = static_cast<const MeasureFormat &>(other); 521fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 522fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Note: Since the ListFormatter depends only on Locale and width, we 523fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // don't have to check it here. 524fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 525fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // differing widths aren't equivalent 526fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (width != rhs.width) { 527fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 528fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 529fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Width the same check locales. 530fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We don't need to check locales if both objects have same cache. 531fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (cache != rhs.cache) { 532fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode status = U_ZERO_ERROR; 533fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *localeId = getLocaleID(status); 534fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *rhsLocaleId = rhs.getLocaleID(status); 535fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 536fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // On failure, assume not equal 537fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 538fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 539fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (uprv_strcmp(localeId, rhsLocaleId) != 0) { 540fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 541fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 542fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 543fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Locales same, check NumberFormat if shared data differs. 544fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return ( 545fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat == rhs.numberFormat || 546fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius **numberFormat == **rhs.numberFormat); 547fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 548fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 549fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusFormat *MeasureFormat::clone() const { 550fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return new MeasureFormat(*this); 551fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 552fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 553fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::format( 554fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Formattable &obj, 555fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 556fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition &pos, 557fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 558fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) return appendTo; 559fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (obj.getType() == Formattable::kObject) { 560fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UObject* formatObj = obj.getObject(); 561fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Measure* amount = dynamic_cast<const Measure*>(formatObj); 562fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (amount != NULL) { 563fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatMeasure( 564fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *amount, **numberFormat, appendTo, pos, status); 565fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 566fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 567fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_ILLEGAL_ARGUMENT_ERROR; 568fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 569fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 570fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 571fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid MeasureFormat::parseObject( 572fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString & /*source*/, 573fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Formattable & /*result*/, 574fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius ParsePosition& /*pos*/) const { 575fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 576fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 577fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 578fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::formatMeasures( 579fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Measure *measures, 580fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t measureCount, 581fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 582fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition &pos, 583fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 584fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 585fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 586fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 587fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (measureCount == 0) { 588fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 589fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 590fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (measureCount == 1) { 591fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatMeasure(measures[0], **numberFormat, appendTo, pos, status); 592fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 593fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (width == UMEASFMT_WIDTH_NUMERIC) { 594fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius Formattable hms[3]; 595fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t bitMap = toHMS(measures, measureCount, hms, status); 596fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (bitMap > 0) { 597fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatNumeric(hms, bitMap, appendTo, status); 598fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 599fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 600fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (pos.getField() != FieldPosition::DONT_CARE) { 601fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatMeasuresSlowTrack( 602fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius measures, measureCount, appendTo, pos, status); 603fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 604fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString *results = new UnicodeString[measureCount]; 605fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (results == NULL) { 606fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 607fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 608fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 609fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < measureCount; ++i) { 610fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat *nf = cache->getIntegerFormat(); 611fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (i == measureCount - 1) { 612fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius nf = numberFormat->get(); 613fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 614fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatMeasure( 615fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius measures[i], 616fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius *nf, 617fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius results[i], 618fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos, 619fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 620fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 621fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter->format(results, measureCount, appendTo, status); 622fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] results; 623fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 624fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 625fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 626fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid MeasureFormat::initMeasureFormat( 627fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Locale &locale, 628fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UMeasureFormatWidth w, 629fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *nfToAdopt, 630fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) { 631fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius static const char *listStyles[] = {"unit", "unit-short", "unit-narrow"}; 632fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalPointer<NumberFormat> nf(nfToAdopt); 633fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 634fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 635fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 636fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const char *name = locale.getName(); 637fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius setLocaleIDs(name, name); 638fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 639fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (!getFromCache(name, cache, status)) { 640fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 641fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 642fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 643fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr( 644fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius PluralRules::createSharedInstance( 645fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius locale, UPLURAL_TYPE_CARDINAL, status), 646fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules); 647fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 648fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 649fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 650fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pluralRules->removeRef(); 651fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (nf.isNull()) { 652fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr( 653fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat::createSharedInstance( 654fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius locale, UNUM_DECIMAL, status), 655fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat); 656fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 657fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 658fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 659fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius numberFormat->removeRef(); 660fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 661fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius adoptNumberFormat(nf.orphan(), status); 662fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 663fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 664fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 665fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 666fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius width = w; 667fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete listFormatter; 668fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter = ListFormatter::createInstance( 669fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius locale, 670fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listStyles[widthToIndex(width)], 671fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 672fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 673fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 674fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusvoid MeasureFormat::adoptNumberFormat( 675fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius NumberFormat *nfToAdopt, UErrorCode &status) { 676fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius LocalPointer<NumberFormat> nf(nfToAdopt); 677fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 678fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 679fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 680fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedNumberFormat *shared = new SharedNumberFormat(nf.getAlias()); 681fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (shared == NULL) { 682fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MEMORY_ALLOCATION_ERROR; 683fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return; 684fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 685fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius nf.orphan(); 686fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius SharedObject::copyPtr(shared, numberFormat); 687fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 688fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 689fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUBool MeasureFormat::setMeasureFormatLocale(const Locale &locale, UErrorCode &status) { 690fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status) || locale == getLocale(status)) { 691fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return FALSE; 692fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 693fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius initMeasureFormat(locale, width, NULL, status); 694fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return U_SUCCESS(status); 695fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 696fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 697fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst NumberFormat &MeasureFormat::getNumberFormat() const { 698fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return **numberFormat; 699fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 700fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 701fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst PluralRules &MeasureFormat::getPluralRules() const { 702fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return **pluralRules; 703fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 704fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 705fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusLocale MeasureFormat::getLocale(UErrorCode &status) const { 706fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return Format::getLocale(ULOC_VALID_LOCALE, status); 707fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 708fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 709fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst char *MeasureFormat::getLocaleID(UErrorCode &status) const { 710fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return Format::getLocaleID(ULOC_VALID_LOCALE, status); 711fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 712fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 713fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::formatMeasure( 714fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Measure &measure, 715fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat &nf, 716fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 717fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition &pos, 718fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 719fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 720fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 721fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 722fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Formattable& amtNumber = measure.getNumber(); 723fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const MeasureUnit& amtUnit = measure.getUnit(); 724fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (isCurrency(amtUnit)) { 725fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UChar isoCode[4]; 726fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius u_charsToUChars(amtUnit.getSubtype(), isoCode, 4); 727fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return cache->getCurrencyFormat(widthToIndex(width))->format( 728fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius new CurrencyAmount(amtNumber, isoCode, status), 729fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 730fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos, 731fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 732fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 733fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const QuantityFormatter *quantityFormatter = getQuantityFormatter( 734fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius amtUnit.getIndex(), widthToIndex(width), status); 735fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 736fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 737fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 738fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return quantityFormatter->format( 739fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius amtNumber, 740fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius nf, 741fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius **pluralRules, 742fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 743fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos, 744fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 745fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 746fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 747fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Formats hours-minutes-seconds as 5:37:23 or similar. 748fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::formatNumeric( 749fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Formattable *hms, // always length 3 750fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t bitMap, // 1=hourset, 2=minuteset, 4=secondset 751fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 752fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 753fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 754fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 755fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 756fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate millis = 757fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius (UDate) (((uprv_trunc(hms[0].getDouble(status)) * 60.0 758fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius + uprv_trunc(hms[1].getDouble(status))) * 60.0 759fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius + uprv_trunc(hms[2].getDouble(status))) * 1000.0); 760fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius switch (bitMap) { 761fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case 5: // hs 762fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case 7: // hms 763fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatNumeric( 764fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius millis, 765fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->getNumericDateFormatters()->hourMinuteSecond, 766fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDAT_SECOND_FIELD, 767fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[2], 768fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 769fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 770fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 771fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case 6: // ms 772fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatNumeric( 773fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius millis, 774fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->getNumericDateFormatters()->minuteSecond, 775fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDAT_SECOND_FIELD, 776fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[2], 777fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 778fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 779fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 780fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius case 3: // hm 781fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return formatNumeric( 782fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius millis, 783fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->getNumericDateFormatters()->hourMinute, 784fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDAT_MINUTE_FIELD, 785fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius hms[1], 786fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 787fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 788fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 789fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius default: 790fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_INTERNAL_PROGRAM_ERROR; 791fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 792fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius break; 793fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 794fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 795fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 796fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 797fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void appendRange( 798fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &src, 799fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t start, 800fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t end, 801fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &dest) { 802fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest.append(src, start, end - start); 803fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 804fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 805fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusstatic void appendRange( 806fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const UnicodeString &src, 807fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t end, 808fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &dest) { 809fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dest.append(src, end, src.length() - end); 810fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 811fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 812fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius// Formats time like 5:37:23 813fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::formatNumeric( 814fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDate date, // Time since epoch 1:30:00 would be 5400000 815fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const DateFormat &dateFmt, // h:mm, m:ss, or h:mm:ss 816fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UDateFormatField smallestField, // seconds in 5:37:23.5 817fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Formattable &smallestAmount, // 23.5 for 5:37:23.5 818fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString &appendTo, 819fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 820fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 821fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 822fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 823fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Format the smallest amount with this object's NumberFormat 824fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString smallestAmountFormatted; 825fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 826fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // We keep track of the integer part of smallest amount so that 827fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // we can replace it later so that we get '0:00:09.3' instead of 828fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // '0:00:9.3' 829fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition intFieldPosition(UNUM_INTEGER_FIELD); 830fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius (*numberFormat)->format( 831fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestAmount, smallestAmountFormatted, intFieldPosition, status); 832fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if ( 833fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius intFieldPosition.getBeginIndex() == 0 && 834fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius intFieldPosition.getEndIndex() == 0) { 835fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_INTERNAL_PROGRAM_ERROR; 836fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 837fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 838fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 839fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // Format time. draft becomes something like '5:30:45' 840fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition smallestFieldPosition(smallestField); 841fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString draft; 842fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius dateFmt.format(date, draft, smallestFieldPosition, status); 843fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 844fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // If we find field for smallest amount replace it with the formatted 845fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // smallest amount from above taking care to replace the integer part 846fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // with what is in original time. For example, If smallest amount 847fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // is 9.35s and the formatted time is 0:00:09 then 9.35 becomes 09.35 848fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius // and replacing yields 0:00:09.35 849fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (smallestFieldPosition.getBeginIndex() != 0 || 850fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestFieldPosition.getEndIndex() != 0) { 851fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange(draft, 0, smallestFieldPosition.getBeginIndex(), appendTo); 852fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 853fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestAmountFormatted, 854fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 0, 855fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius intFieldPosition.getBeginIndex(), 856fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 857fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 858fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius draft, 859fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestFieldPosition.getBeginIndex(), 860fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestFieldPosition.getEndIndex(), 861fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 862fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 863fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestAmountFormatted, 864fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius intFieldPosition.getEndIndex(), 865fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 866fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendRange( 867fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius draft, 868fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius smallestFieldPosition.getEndIndex(), 869fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo); 870fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 871fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo.append(draft); 872fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 873fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 874fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 875fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 876fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusconst QuantityFormatter *MeasureFormat::getQuantityFormatter( 877fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t index, 878fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t widthIndex, 879fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode &status) const { 880fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 881fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 882fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 883fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const QuantityFormatter *formatters = 884fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius cache->formatters[index]; 885fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (formatters[widthIndex].isValid()) { 886fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return &formatters[widthIndex]; 887fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 888fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (formatters[UMEASFMT_WIDTH_SHORT].isValid()) { 889fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return &formatters[UMEASFMT_WIDTH_SHORT]; 890fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 891fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (formatters[UMEASFMT_WIDTH_WIDE].isValid()) { 892fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return &formatters[UMEASFMT_WIDTH_WIDE]; 893fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 894fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status = U_MISSING_RESOURCE_ERROR; 895fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return NULL; 896fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 897fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius 898fceb39872958b9fa2505e63f8b8699a9e0f882f4ccorneliusUnicodeString &MeasureFormat::formatMeasuresSlowTrack( 899fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const Measure *measures, 900fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t measureCount, 901fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString& appendTo, 902fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition& pos, 903fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UErrorCode& status) const { 904fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 905fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 906fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 907fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition dontCare(FieldPosition::DONT_CARE); 908fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius FieldPosition fpos(pos.getField()); 909fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius UnicodeString *results = new UnicodeString[measureCount]; 910fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t fieldPositionFoundIndex = -1; 911fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius for (int32_t i = 0; i < measureCount; ++i) { 912fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius const NumberFormat *nf = cache->getIntegerFormat(); 913fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (i == measureCount - 1) { 914fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius nf = numberFormat->get(); 915fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 916fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (fieldPositionFoundIndex == -1) { 917fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatMeasure(measures[i], *nf, results[i], fpos, status); 918fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 919fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] results; 920fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 921fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 922fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (fpos.getBeginIndex() != 0 || fpos.getEndIndex() != 0) { 923fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fieldPositionFoundIndex = i; 924fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 925fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } else { 926fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius formatMeasure(measures[i], *nf, results[i], dontCare, status); 927fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 928fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 929fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius int32_t offset; 930fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius listFormatter->format( 931fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius results, 932fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius measureCount, 933fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius appendTo, 934fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius fieldPositionFoundIndex, 935fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius offset, 936fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius status); 937fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (U_FAILURE(status)) { 938fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] results; 939fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 940fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 941fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius if (offset != -1) { 942fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos.setBeginIndex(fpos.getBeginIndex() + offset); 943fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius pos.setEndIndex(fpos.getEndIndex() + offset); 944fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius } 945fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius delete [] results; 946fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius return appendTo; 947fceb39872958b9fa2505e63f8b8699a9e0f882f4ccornelius} 94883a171d1a62abf406f7f44ae671823d5ec20db7dCraig Cornelius 949ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(const Locale& locale, 950ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru UErrorCode& ec) { 951ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru CurrencyFormat* fmt = NULL; 952ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_SUCCESS(ec)) { 953ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fmt = new CurrencyFormat(locale, ec); 954ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(ec)) { 955ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru delete fmt; 956ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fmt = NULL; 957ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 958ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 959ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return fmt; 960ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 961ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 962ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruMeasureFormat* U_EXPORT2 MeasureFormat::createCurrencyFormat(UErrorCode& ec) { 963ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (U_FAILURE(ec)) { 964ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return NULL; 965ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 966ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return MeasureFormat::createCurrencyFormat(Locale::getDefault(), ec); 967ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 968ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 969ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 970ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 971ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif /* #if !UCONFIG_NO_FORMATTING */ 972