]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/i18n/tmutfmt.cpp
ICU-57166.0.1.tar.gz
[apple/icu.git] / icuSources / i18n / tmutfmt.cpp
index f8ad9a394c0ca7e41a8734127718e425863854b2..fa31d7b3c1815cc50375dea3ac6f81a551c67d06 100644 (file)
@@ -1,21 +1,26 @@
 /*
  *******************************************************************************
- * Copyright (C) 2008-2011, Google, International Business Machines Corporation
- * and  others. All Rights Reserved.                                           
+ * Copyright (C) 2008-2015, Google, International Business Machines Corporation
+ * and others. All Rights Reserved.
  *******************************************************************************
  */
 
-#include <typeinfo>  // for 'typeid' to work
-
 #include "unicode/tmutfmt.h"
 
 #if !UCONFIG_NO_FORMATTING
 
+#include "unicode/decimfmt.h"
+#include "unicode/localpointer.h"
+#include "plurrule_impl.h"
+#include "uvector.h"
+#include "charstr.h"
 #include "cmemory.h"
 #include "cstring.h"
 #include "hash.h"
 #include "uresimp.h"
+#include "ureslocs.h"
 #include "unicode/msgfmt.h"
+#include "uassert.h"
 
 #define LEFT_CURLY_BRACKET  ((UChar)0x007B)
 #define RIGHT_CURLY_BRACKET ((UChar)0x007D)
@@ -73,82 +78,80 @@ static const UChar PLURAL_COUNT_ZERO[] = {LOW_Z, LOW_E, LOW_R, LOW_O, 0};
 static const UChar PLURAL_COUNT_ONE[] = {LOW_O, LOW_N, LOW_E, 0};
 static const UChar PLURAL_COUNT_TWO[] = {LOW_T, LOW_W, LOW_O, 0};
 
-
-TimeUnitFormat::TimeUnitFormat(UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(Locale::getDefault(), kFull, status);
+TimeUnitFormat::TimeUnitFormat(UErrorCode& status) {
+    initMeasureFormat(Locale::getDefault(), UMEASFMT_WIDTH_WIDE, NULL, status);
+    create(UTMUTFMT_FULL_STYLE, status);
 }
 
 
-TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(locale, kFull, status);
+TimeUnitFormat::TimeUnitFormat(const Locale& locale, UErrorCode& status) {
+    initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status);
+    create(UTMUTFMT_FULL_STYLE, status);
 }
 
 
-TimeUnitFormat::TimeUnitFormat(const Locale& locale, EStyle style, UErrorCode& status)
-:   fNumberFormat(NULL),
-    fPluralRules(NULL) {
-    create(locale, style, status);
+TimeUnitFormat::TimeUnitFormat(const Locale& locale, UTimeUnitFormatStyle style, UErrorCode& status) {
+    switch (style) {
+    case UTMUTFMT_FULL_STYLE:
+        initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status);
+        break;
+    case UTMUTFMT_ABBREVIATED_STYLE:
+        initMeasureFormat(locale, UMEASFMT_WIDTH_SHORT, NULL, status);
+        break;
+    default:
+        initMeasureFormat(locale, UMEASFMT_WIDTH_WIDE, NULL, status);
+        break;
+    }
+    create(style, status);
 }
 
-
 TimeUnitFormat::TimeUnitFormat(const TimeUnitFormat& other)
 :   MeasureFormat(other),
-    fNumberFormat(NULL),
-    fPluralRules(NULL),
-    fStyle(kFull)
+    fStyle(other.fStyle)
 {
     for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        fTimeUnitToCountToPatterns[i] = NULL;
+        UErrorCode status = U_ZERO_ERROR;
+        fTimeUnitToCountToPatterns[i] = initHash(status);
+        if (U_SUCCESS(status)) {
+            copyHash(other.fTimeUnitToCountToPatterns[i], fTimeUnitToCountToPatterns[i], status);
+        } else {
+            delete fTimeUnitToCountToPatterns[i];
+            fTimeUnitToCountToPatterns[i] = NULL;
+        }
     }
-    *this = other;
 }
 
 
 TimeUnitFormat::~TimeUnitFormat() {
-    delete fNumberFormat;
-    fNumberFormat = NULL;
     for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
         deleteHash(fTimeUnitToCountToPatterns[i]);
         fTimeUnitToCountToPatterns[i] = NULL;
     }
-    delete fPluralRules;
-    fPluralRules = NULL;
 }
 
 
-Format* 
+Format*
 TimeUnitFormat::clone(void) const {
     return new TimeUnitFormat(*this);
 }
 
 
-TimeUnitFormat& 
+TimeUnitFormat&
 TimeUnitFormat::operator=(const TimeUnitFormat& other) {
     if (this == &other) {
         return *this;
     }
-    delete fNumberFormat;
+    MeasureFormat::operator=(other);
     for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
         deleteHash(fTimeUnitToCountToPatterns[i]);
         fTimeUnitToCountToPatterns[i] = NULL;
     }
-    delete fPluralRules;
-    if (other.fNumberFormat) {
-        fNumberFormat = (NumberFormat*)other.fNumberFormat->clone();
-    } else {
-        fNumberFormat = NULL;
-    }
-    fLocale = other.fLocale;
     for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
@@ -160,83 +163,16 @@ TimeUnitFormat::operator=(const TimeUnitFormat& other) {
             delete fTimeUnitToCountToPatterns[i];
             fTimeUnitToCountToPatterns[i] = NULL;
         }
-    } 
-    if (other.fPluralRules) {
-        fPluralRules = (PluralRules*)other.fPluralRules->clone();
-    } else {
-        fPluralRules = NULL;
     }
     fStyle = other.fStyle;
     return *this;
 }
 
-
-UBool 
-TimeUnitFormat::operator==(const Format& other) const {
-    if (typeid(*this) == typeid(other)) {
-        TimeUnitFormat* fmt = (TimeUnitFormat*)&other;
-        UBool ret =  ( ((fNumberFormat && fmt->fNumberFormat && *fNumberFormat == *fmt->fNumberFormat)
-                            || fNumberFormat == fmt->fNumberFormat ) 
-                        && fLocale == fmt->fLocale 
-                        && ((fPluralRules && fmt->fPluralRules && *fPluralRules == *fmt->fPluralRules) 
-                            || fPluralRules == fmt->fPluralRules) 
-                        && fStyle == fmt->fStyle); 
-        if (ret) {
-            for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-                 i < TimeUnit::UTIMEUNIT_FIELD_COUNT && ret;
-                 i = (TimeUnit::UTimeUnitFields)(i+1)) {
-                ret = fTimeUnitToCountToPatterns[i]->equals(*(fmt->fTimeUnitToCountToPatterns[i]));
-            }
-        }
-        return ret;
-    }
-    return false;
-}
-
-
-UnicodeString& 
-TimeUnitFormat::format(const Formattable& obj, UnicodeString& toAppendTo,
-                       FieldPosition& pos, UErrorCode& status) const {
-    if (U_FAILURE(status)) {
-        return toAppendTo;
-    }
-    if (obj.getType() == Formattable::kObject) {
-        const UObject* formatObj = obj.getObject();
-        const TimeUnitAmount* amount = dynamic_cast<const TimeUnitAmount*>(formatObj);
-        if (amount != NULL){
-            Hashtable* countToPattern = fTimeUnitToCountToPatterns[amount->getTimeUnitField()];
-            double number;
-            const Formattable& amtNumber = amount->getNumber();
-            if (amtNumber.getType() == Formattable::kDouble) {
-                number = amtNumber.getDouble();
-            } else if (amtNumber.getType() == Formattable::kLong) {
-                number = amtNumber.getLong();
-            } else {
-                status = U_ILLEGAL_ARGUMENT_ERROR;
-                return toAppendTo;
-            }
-            UnicodeString count = fPluralRules->select(number);
-#ifdef TMUTFMT_DEBUG
-            char result[1000];
-            count.extract(0, count.length(), result, "UTF-8");
-            std::cout << "number: " << number << "; format plural count: " << result << "\n";           
-#endif
-            MessageFormat* pattern = ((MessageFormat**)countToPattern->get(count))[fStyle];
-            Formattable formattable[1];
-            formattable[0].setDouble(number);
-            return pattern->format(formattable, 1, toAppendTo, pos, status);
-        }
-    }
-    status = U_ILLEGAL_ARGUMENT_ERROR;
-    return toAppendTo;
-}
-
-
-void 
-TimeUnitFormat::parseObject(const UnicodeString& source, 
+void
+TimeUnitFormat::parseObject(const UnicodeString& source,
                             Formattable& result,
                             ParsePosition& pos) const {
-    double resultNumber = -1; 
+    Formattable resultNumber(0.0);
     UBool withNumberFormat = false;
     TimeUnit::UTimeUnitFields resultTimeUnit = TimeUnit::UTIMEUNIT_FIELD_COUNT;
     int32_t oldPos = pos.getIndex();
@@ -246,7 +182,7 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
 #ifdef TMUTFMT_DEBUG
     char res[1000];
     source.extract(0, source.length(), res, "UTF-8");
-    std::cout << "parse source: " << res << "\n";           
+    std::cout << "parse source: " << res << "\n";
 #endif
     // parse by iterating through all available patterns
     // and looking for the longest match.
@@ -254,19 +190,20 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
         Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
-        int32_t elemPos = -1;
+        int32_t elemPos = UHASH_FIRST;
         const UHashElement* elem = NULL;
         while ((elem = countToPatterns->nextElement(elemPos)) != NULL){
             const UHashTok keyTok = elem->key;
             UnicodeString* count = (UnicodeString*)keyTok.pointer;
 #ifdef TMUTFMT_DEBUG
             count->extract(0, count->length(), res, "UTF-8");
-            std::cout << "parse plural count: " << res << "\n";           
+            std::cout << "parse plural count: " << res << "\n";
 #endif
             const UHashTok valueTok = elem->value;
             // the value is a pair of MessageFormat*
             MessageFormat** patterns = (MessageFormat**)valueTok.pointer;
-            for (EStyle style = kFull; style < kTotal; style = (EStyle)(style + 1)) {
+            for (UTimeUnitFormatStyle style = UTMUTFMT_FULL_STYLE; style < UTMUTFMT_FORMAT_STYLE_COUNT;
+                 style = (UTimeUnitFormatStyle)(style + 1)) {
                 MessageFormat* pattern = patterns[style];
                 pos.setErrorIndex(-1);
                 pos.setIndex(oldPos);
@@ -279,26 +216,21 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
     #ifdef TMUTFMT_DEBUG
                 std::cout << "parsed.getType: " << parsed.getType() << "\n";
     #endif
-                double tmpNumber = 0;
+                Formattable tmpNumber(0.0);
                 if (pattern->getArgTypeCount() != 0) {
-                    // pattern with Number as beginning, such as "{0} d".
-                    // check to make sure that the timeUnit is consistent
                     Formattable& temp = parsed[0];
-                    if (temp.getType() == Formattable::kDouble) {
-                        tmpNumber = temp.getDouble();
-                    } else if (temp.getType() == Formattable::kLong) {
-                        tmpNumber = temp.getLong();
+                    if (temp.getType() == Formattable::kString) {
+                        UnicodeString tmpString;
+                        UErrorCode pStatus = U_ZERO_ERROR;
+                        getNumberFormat().parse(temp.getString(tmpString), tmpNumber, pStatus);
+                        if (U_FAILURE(pStatus)) {
+                            continue;
+                        }
+                    } else if (temp.isNumeric()) {
+                        tmpNumber = temp;
                     } else {
                         continue;
                     }
-                    UnicodeString select = fPluralRules->select(tmpNumber);
-    #ifdef TMUTFMT_DEBUG
-                    select.extract(0, select.length(), res, "UTF-8");
-                    std::cout << "parse plural select count: " << res << "\n"; 
-    #endif
-                    if (*count != select) {
-                        continue;
-                    }
                 }
                 int32_t parseDistance = pos.getIndex() - oldPos;
                 if (parseDistance > longestParseDistance) {
@@ -323,16 +255,16 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
      */
     if (withNumberFormat == false && longestParseDistance != 0) {
         // set the number using plurrual count
-        if ( *countOfLongestMatch == PLURAL_COUNT_ZERO ) {
-            resultNumber = 0;
-        } else if ( *countOfLongestMatch == PLURAL_COUNT_ONE ) {
-            resultNumber = 1;
-        } else if ( *countOfLongestMatch == PLURAL_COUNT_TWO ) {
-            resultNumber = 2;
+        if (0 == countOfLongestMatch->compare(PLURAL_COUNT_ZERO, 4)) {
+            resultNumber = Formattable(0.0);
+        } else if (0 == countOfLongestMatch->compare(PLURAL_COUNT_ONE, 3)) {
+            resultNumber = Formattable(1.0);
+        } else if (0 == countOfLongestMatch->compare(PLURAL_COUNT_TWO, 3)) {
+            resultNumber = Formattable(2.0);
         } else {
             // should not happen.
             // TODO: how to handle?
-            resultNumber = 3;
+            resultNumber = Formattable(3.0);
         }
     }
     if (longestParseDistance == 0) {
@@ -340,9 +272,9 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
         pos.setErrorIndex(0);
     } else {
         UErrorCode status = U_ZERO_ERROR;
-        TimeUnitAmount* tmutamt = new TimeUnitAmount(resultNumber, resultTimeUnit, status);
+        LocalPointer<TimeUnitAmount> tmutamt(new TimeUnitAmount(resultNumber, resultTimeUnit, status), status);
         if (U_SUCCESS(status)) {
-            result.adoptObject(tmutamt);
+            result.adoptObject(tmutamt.orphan());
             pos.setIndex(newPos);
             pos.setErrorIndex(-1);
         } else {
@@ -352,23 +284,25 @@ TimeUnitFormat::parseObject(const UnicodeString& source,
     }
 }
 
-
 void
-TimeUnitFormat::create(const Locale& locale, EStyle style, UErrorCode& status) {
+TimeUnitFormat::create(UTimeUnitFormatStyle style, UErrorCode& status) {
+    // fTimeUnitToCountToPatterns[] must have its elements initialized to NULL first
+    // before checking for failure status.
+    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
+         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
+         i = (TimeUnit::UTimeUnitFields)(i+1)) {
+        fTimeUnitToCountToPatterns[i] = NULL;
+    }
+
     if (U_FAILURE(status)) {
         return;
     }
-    if (style < kFull || style > kAbbreviate) {
+    if (style < UTMUTFMT_FULL_STYLE || style >= UTMUTFMT_FORMAT_STYLE_COUNT) {
         status = U_ILLEGAL_ARGUMENT_ERROR;
         return;
     }
     fStyle = style;
-    fLocale = locale;
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        fTimeUnitToCountToPatterns[i] = NULL;
-    }
+
     //TODO: format() and parseObj() are const member functions,
     //so, can not do lazy initialization in C++.
     //setup has to be done in constructors.
@@ -376,17 +310,27 @@ TimeUnitFormat::create(const Locale& locale, EStyle style, UErrorCode& status) {
     //In Java, create an empty instance does not setup locale as
     //default locale. If it followed by setNumberFormat(),
     //in format(), the locale will set up as the locale in fNumberFormat.
-    //But in C++, this sets the locale as the default locale. 
+    //But in C++, this sets the locale as the default locale.
     setup(status);
 }
 
-void 
+void
 TimeUnitFormat::setup(UErrorCode& err) {
     initDataMembers(err);
-    readFromCurrentLocale(kFull, gUnitsTag, err);
-    checkConsistency(kFull, gUnitsTag, err);
-    readFromCurrentLocale(kAbbreviate, gShortUnitsTag, err);
-    checkConsistency(kAbbreviate, gShortUnitsTag, err);
+
+    UVector pluralCounts(0, uhash_compareUnicodeString, 6, err);
+    LocalPointer<StringEnumeration> keywords(getPluralRules().getKeywords(err), err);
+    if (U_FAILURE(err)) {
+        return;
+    }
+    UnicodeString* pluralCount;
+    while ((pluralCount = const_cast<UnicodeString*>(keywords->snext(err))) != NULL) {
+      pluralCounts.addElement(pluralCount, err);
+    }
+    readFromCurrentLocale(UTMUTFMT_FULL_STYLE, gUnitsTag, pluralCounts, err);
+    checkConsistency(UTMUTFMT_FULL_STYLE, gUnitsTag, err);
+    readFromCurrentLocale(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, pluralCounts, err);
+    checkConsistency(UTMUTFMT_ABBREVIATED_STYLE, gShortUnitsTag, err);
 }
 
 
@@ -395,11 +339,6 @@ TimeUnitFormat::initDataMembers(UErrorCode& err){
     if (U_FAILURE(err)) {
         return;
     }
-    if (fNumberFormat == NULL) {
-        fNumberFormat = NumberFormat::createInstance(fLocale, err);
-    }
-    delete fPluralRules;
-    fPluralRules = PluralRules::forLocale(fLocale, err);
     for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
          i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
          i = (TimeUnit::UTimeUnitFields)(i+1)) {
@@ -408,11 +347,9 @@ TimeUnitFormat::initDataMembers(UErrorCode& err){
     }
 }
 
-
-
-
 void
-TimeUnitFormat::readFromCurrentLocale(EStyle style, const char* key, UErrorCode& err) {
+TimeUnitFormat::readFromCurrentLocale(UTimeUnitFormatStyle style, const char* key,
+                                      const UVector& pluralCounts, UErrorCode& err) {
     if (U_FAILURE(err)) {
         return;
     }
@@ -421,123 +358,109 @@ TimeUnitFormat::readFromCurrentLocale(EStyle style, const char* key, UErrorCode&
     // status is an error code used in resource lookup.
     // status does not affect "err".
     UErrorCode status = U_ZERO_ERROR;
-    UResourceBundle *rb, *unitsRes;
-    rb = ures_open(NULL, fLocale.getName(), &status);
-    unitsRes = ures_getByKey(rb, key, NULL, &status);
+    LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, getLocaleID(status), &status));
+
+    LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, NULL, &status));
+    ures_getByKey(unitsRes.getAlias(), "duration", unitsRes.getAlias(), &status);
     if (U_FAILURE(status)) {
-        ures_close(unitsRes);
-        ures_close(rb);
         return;
     }
-    int32_t size = ures_getSize(unitsRes);
+    int32_t size = ures_getSize(unitsRes.getAlias());
     for ( int32_t index = 0; index < size; ++index) {
+        status = U_ZERO_ERROR;
         // resource of one time unit
-        UResourceBundle* oneTimeUnit = ures_getByIndex(unitsRes, index,
-                                                       NULL, &status);
-        if (U_SUCCESS(status)) {
-            const char* timeUnitName = ures_getKey(oneTimeUnit);
-            if (timeUnitName == NULL) {
-                ures_close(oneTimeUnit);
-                continue;
+        LocalUResourceBundlePointer oneTimeUnit(
+                ures_getByIndex(unitsRes.getAlias(), index, NULL, &status));
+        if (U_FAILURE(status)) {
+            continue;
+        }
+        const char* timeUnitName = ures_getKey(oneTimeUnit.getAlias());
+        if (timeUnitName == NULL) {
+            continue;
+        }
+        LocalUResourceBundlePointer countsToPatternRB(
+                ures_getByKey(unitsRes.getAlias(), timeUnitName, NULL, &status));
+        if (countsToPatternRB.isNull() || U_FAILURE(status)) {
+            continue;
+        }
+        TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT;
+        if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_YEAR;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_MONTH;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_DAY;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_HOUR;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_MINUTE;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_SECOND;
+        } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) {
+            timeUnitField = TimeUnit::UTIMEUNIT_WEEK;
+        } else {
+            continue;
+        }
+        LocalPointer<Hashtable> localCountToPatterns;
+        Hashtable *countToPatterns = fTimeUnitToCountToPatterns[timeUnitField];
+        if (countToPatterns == NULL) {
+            localCountToPatterns.adoptInsteadAndCheckErrorCode(initHash(err), err);
+            countToPatterns = localCountToPatterns.getAlias();
+            if (U_FAILURE(err)) {
+                return;
             }
-            UResourceBundle* countsToPatternRB = ures_getByKey(unitsRes, 
-                                                             timeUnitName, 
-                                                             NULL, &status);
-            if (countsToPatternRB == NULL || U_FAILURE(status)) {
-                ures_close(countsToPatternRB);
-                ures_close(oneTimeUnit);
+        }
+        int32_t count = ures_getSize(countsToPatternRB.getAlias());
+        const char*  pluralCount;
+        for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
+            // resource of count to pattern
+            status = U_ZERO_ERROR;
+            UnicodeString pattern =
+                ures_getNextUnicodeString(countsToPatternRB.getAlias(), &pluralCount, &status);
+            if (U_FAILURE(status)) {
                 continue;
             }
-            TimeUnit::UTimeUnitFields timeUnitField = TimeUnit::UTIMEUNIT_FIELD_COUNT;
-            if ( uprv_strcmp(timeUnitName, gTimeUnitYear) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_YEAR;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMonth) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_MONTH;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitDay) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_DAY;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitHour) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_HOUR;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitMinute) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_MINUTE;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitSecond) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_SECOND;
-            } else if ( uprv_strcmp(timeUnitName, gTimeUnitWeek) == 0 ) {
-                timeUnitField = TimeUnit::UTIMEUNIT_WEEK;
-            } else {
-                ures_close(countsToPatternRB);
-                ures_close(oneTimeUnit);
+            UnicodeString pluralCountUniStr(pluralCount, -1, US_INV);
+            if (!pluralCounts.contains(&pluralCountUniStr)) {
                 continue;
             }
-            Hashtable* countToPatterns = fTimeUnitToCountToPatterns[timeUnitField];
-            if (countToPatterns == NULL) {
-                countToPatterns = initHash(err);
-                if (U_FAILURE(err)) {
-                    ures_close(countsToPatternRB);
-                    ures_close(oneTimeUnit);
-                    delete countToPatterns;
-                    break;
-                }
+            LocalPointer<MessageFormat> messageFormat(new MessageFormat(pattern, getLocale(err), err), err);
+            if (U_FAILURE(err)) {
+                return;
             }
-            int32_t count = ures_getSize(countsToPatternRB);
-            const UChar* pattern;
-            const char*  pluralCount;
-            int32_t ptLength; 
-            for ( int32_t pluralIndex = 0; pluralIndex < count; ++pluralIndex) {
-                // resource of count to pattern
-                pattern = ures_getNextString(countsToPatternRB, &ptLength,
-                                             &pluralCount, &status);
-                if (U_FAILURE(status)) {
-                    continue;
+            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCountUniStr);
+            if (formatters == NULL) {
+                LocalMemory<MessageFormat *> localFormatters(
+                        (MessageFormat **)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
+                if (localFormatters.isNull()) {
+                    err = U_MEMORY_ALLOCATION_ERROR;
+                    return;
                 }
-                MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
-                if ( U_SUCCESS(err) ) {
-                  if (fNumberFormat != NULL) {
-                    messageFormat->setFormat(0, *fNumberFormat);
-                  }
-                  MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
-                  if (formatters == NULL) {
-                    formatters = (MessageFormat**)uprv_malloc(kTotal*sizeof(MessageFormat*));
-                    formatters[kFull] = NULL;
-                    formatters[kAbbreviate] = NULL;
-                    countToPatterns->put(pluralCount, formatters, err);
-                    if (U_FAILURE(err)) {
-                        uprv_free(formatters);
-                    }
-                  } 
-                  if (U_SUCCESS(err)) {
-                      //delete formatters[style];
-                      formatters[style] = messageFormat;
-                  }
-                } 
+                localFormatters[UTMUTFMT_FULL_STYLE] = NULL;
+                localFormatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
+                countToPatterns->put(pluralCountUniStr, localFormatters.getAlias(), err);
                 if (U_FAILURE(err)) {
-                    ures_close(countsToPatternRB);
-                    ures_close(oneTimeUnit);
-                    ures_close(unitsRes);
-                    ures_close(rb);
-                    delete messageFormat;
-                    delete countToPatterns;
                     return;
                 }
+                formatters = localFormatters.orphan();
             }
-            if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
-                fTimeUnitToCountToPatterns[timeUnitField] = countToPatterns;
-            }
-            ures_close(countsToPatternRB);
+            //delete formatters[style];
+            formatters[style] = messageFormat.orphan();
+        }
+        if (fTimeUnitToCountToPatterns[timeUnitField] == NULL) {
+            fTimeUnitToCountToPatterns[timeUnitField] = localCountToPatterns.orphan();
         }
-        ures_close(oneTimeUnit);
     }
-    ures_close(unitsRes);
-    ures_close(rb);
 }
 
 
-void 
-TimeUnitFormat::checkConsistency(EStyle style, const char* key, UErrorCode& err) {
+void
+TimeUnitFormat::checkConsistency(UTimeUnitFormatStyle style, const char* key, UErrorCode& err) {
     if (U_FAILURE(err)) {
         return;
     }
     // there should be patterns for each plural rule in each time unit.
-    // For each time unit, 
+    // For each time unit,
     //     for each plural rule, following is unit pattern fall-back rule:
     //         ( for example: "one" hour )
     //         look for its unit pattern in its locale tree.
@@ -548,43 +471,41 @@ TimeUnitFormat::checkConsistency(EStyle style, const char* key, UErrorCode& err)
     //         fallback to plural count "other",
     //         look for the pattern of "other" in the locale tree:
     //         "de_DE" to "de" to "root".
-    //         If not found, fall back to value of 
-    //         static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h". 
+    //         If not found, fall back to value of
+    //         static variable DEFAULT_PATTERN_FOR_xxx, such as "{0} h".
     //
     // Following is consistency check to create pattern for each
     // plural rule in each time unit using above fall-back rule.
     //
-    StringEnumeration* keywords = fPluralRules->getKeywords(err);
-    if (U_SUCCESS(err)) {
-        const char* pluralCount;
-        while ((pluralCount = keywords->next(NULL, err)) != NULL) {
-            if ( U_SUCCESS(err) ) {
-                for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
-                    // for each time unit, 
-                    // get all the patterns for each plural rule in this locale.
-                    Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
-                    if ( countToPatterns == NULL ) {
-                        countToPatterns = initHash(err);
-                        if (U_FAILURE(err)) {
-                            delete countToPatterns;
-                            return;
-                        }
-                        fTimeUnitToCountToPatterns[i] = countToPatterns;
-                    }
-                    MessageFormat** formatters = (MessageFormat**)countToPatterns->get(pluralCount);
-                    if( formatters == NULL || formatters[style] == NULL ) {
-                        // look through parents
-                        const char* localeName = fLocale.getName();
-                        searchInLocaleChain(style, key, localeName,
-                                            (TimeUnit::UTimeUnitFields)i, 
-                                            pluralCount, pluralCount, 
-                                            countToPatterns, err);
-                    }
+    LocalPointer<StringEnumeration> keywords(
+            getPluralRules().getKeywords(err), err);
+    const UnicodeString* pluralCount;
+    while (U_SUCCESS(err) && (pluralCount = keywords->snext(err)) != NULL) {
+        for (int32_t i = 0; i < TimeUnit::UTIMEUNIT_FIELD_COUNT; ++i) {
+            // for each time unit,
+            // get all the patterns for each plural rule in this locale.
+            Hashtable* countToPatterns = fTimeUnitToCountToPatterns[i];
+            if ( countToPatterns == NULL ) {
+                fTimeUnitToCountToPatterns[i] = countToPatterns = initHash(err);
+                if (U_FAILURE(err)) {
+                    return;
                 }
             }
+            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(*pluralCount);
+            if( formatters == NULL || formatters[style] == NULL ) {
+                // look through parents
+                const char* localeName = getLocaleID(err);
+                CharString pluralCountChars;
+                pluralCountChars.appendInvariantChars(*pluralCount, err);
+                searchInLocaleChain(style, key, localeName,
+                                    (TimeUnit::UTimeUnitFields)i,
+                                    *pluralCount, pluralCountChars.data(),
+                                    countToPatterns, err);
+            }
+            // TODO: what to do with U_FAILURE(err) at this point.
+            //       As is, the outer loop continues to run, but does nothing.
         }
     }
-    delete keywords;
 }
 
 
@@ -594,14 +515,14 @@ TimeUnitFormat::checkConsistency(EStyle style, const char* key, UErrorCode& err)
 // searchPluralCount is the fallback plural count.
 // For example, to search for pattern for ""one" hour",
 // "one" is the srcPluralCount,
-// if the pattern is not found even in root, fallback to 
-// using patterns of plural count "other", 
+// if the pattern is not found even in root, fallback to
+// using patterns of plural count "other",
 // then, "other" is the searchPluralCount.
-void 
-TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key, const char* localeName,
+void
+TimeUnitFormat::searchInLocaleChain(UTimeUnitFormatStyle style, const char* key, const char* localeName,
                                 TimeUnit::UTimeUnitFields srcTimeUnitField,
-                                const char* srcPluralCount,
-                                const char* searchPluralCount, 
+                                const UnicodeString& srcPluralCount,
+                                const char* searchPluralCount,
                                 Hashtable* countToPatterns,
                                 UErrorCode& err) {
     if (U_FAILURE(err)) {
@@ -611,52 +532,42 @@ TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key, const char* l
     char parentLocale[ULOC_FULLNAME_CAPACITY];
     uprv_strcpy(parentLocale, localeName);
     int32_t locNameLen;
+    U_ASSERT(countToPatterns != NULL);
     while ((locNameLen = uloc_getParent(parentLocale, parentLocale,
                                         ULOC_FULLNAME_CAPACITY, &status)) >= 0){
         // look for pattern for srcPluralCount in locale tree
-        UResourceBundle *rb, *unitsRes, *countsToPatternRB;
-        rb = ures_open(NULL, parentLocale, &status);
-        unitsRes = ures_getByKey(rb, key, NULL, &status);
+        LocalUResourceBundlePointer rb(ures_open(U_ICUDATA_UNIT, parentLocale, &status));
+        LocalUResourceBundlePointer unitsRes(ures_getByKey(rb.getAlias(), key, NULL, &status));
         const char* timeUnitName = getTimeUnitName(srcTimeUnitField, status);
-        countsToPatternRB = ures_getByKey(unitsRes, timeUnitName, NULL, &status);
+        LocalUResourceBundlePointer countsToPatternRB(ures_getByKey(unitsRes.getAlias(), timeUnitName, NULL, &status));
         const UChar* pattern;
         int32_t      ptLength;
-        pattern = ures_getStringByKeyWithFallback(countsToPatternRB, searchPluralCount, &ptLength, &status);
+        pattern = ures_getStringByKeyWithFallback(countsToPatternRB.getAlias(), searchPluralCount, &ptLength, &status);
         if (U_SUCCESS(status)) {
             //found
-            MessageFormat* messageFormat = new MessageFormat(pattern, fLocale, err);
-            if (U_SUCCESS(err)) {
-                if (fNumberFormat != NULL) {
-                    messageFormat->setFormat(0, *fNumberFormat);
-                }
-                MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
-                if (formatters == NULL) {
-                    formatters = (MessageFormat**)uprv_malloc(kTotal*sizeof(MessageFormat*));
-                    formatters[kFull] = NULL;
-                    formatters[kAbbreviate] = NULL;
-                    countToPatterns->put(srcPluralCount, formatters, err);
-                    if (U_FAILURE(err)) {
-                        uprv_free(formatters);
-                        delete messageFormat;
-                    }
-                } 
-                if (U_SUCCESS(err)) {
-                    //delete formatters[style];
-                    formatters[style] = messageFormat;
+            LocalPointer<MessageFormat> messageFormat(
+                new MessageFormat(UnicodeString(TRUE, pattern, ptLength), getLocale(err), err), err);
+            if (U_FAILURE(err)) {
+                return;
+            }
+            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
+            if (formatters == NULL) {
+                LocalMemory<MessageFormat *> localFormatters(
+                        (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
+                formatters = localFormatters.getAlias();
+                localFormatters[UTMUTFMT_FULL_STYLE] = NULL;
+                localFormatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
+                countToPatterns->put(srcPluralCount, localFormatters.orphan(), err);
+                if (U_FAILURE(err)) {
+                    return;
                 }
-            } else {
-                delete messageFormat;
             }
-            ures_close(countsToPatternRB);
-            ures_close(unitsRes);
-            ures_close(rb);
+            //delete formatters[style];
+            formatters[style] = messageFormat.orphan();
             return;
         }
-        ures_close(countsToPatternRB);
-        ures_close(unitsRes);
-        ures_close(rb);
         status = U_ZERO_ERROR;
-        if ( locNameLen ==0 ) {
+        if (locNameLen == 0) {
             break;
         }
     }
@@ -667,16 +578,18 @@ TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key, const char* l
 #ifdef TMUTFMT_DEBUG
         std::cout << "loop into searchInLocaleChain since Short-Long-Alternative \n";
 #endif
-        char pLocale[ULOC_FULLNAME_CAPACITY];
-        uprv_strcpy(pLocale, localeName);
+        CharString pLocale(localeName, -1, err);
         // Add an underscore at the tail of locale name,
         // so that searchInLocaleChain will check the current locale before falling back
-        uprv_strcat(pLocale, "_");
-        searchInLocaleChain(style, gUnitsTag, pLocale, srcTimeUnitField, srcPluralCount,
+        pLocale.append('_', err);
+        searchInLocaleChain(style, gUnitsTag, pLocale.data(), srcTimeUnitField, srcPluralCount,
                              searchPluralCount, countToPatterns, err);
-        if (countToPatterns != NULL) {
-            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
-            if (formatters != NULL && formatters[style] != NULL) return;
+        if (U_FAILURE(err)) {
+            return;
+        }
+        MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
+        if (formatters != NULL && formatters[style] != NULL) {
+            return;
         }
     }
 
@@ -684,93 +597,81 @@ TimeUnitFormat::searchInLocaleChain(EStyle style, const char* key, const char* l
     // fall-back to plural count "other"
     if ( uprv_strcmp(searchPluralCount, gPluralCountOther) == 0 ) {
         // set default fall back the same as the resource in root
-        MessageFormat* messageFormat = NULL;
+        LocalPointer<MessageFormat> messageFormat;
+        const UChar *pattern = NULL;
         if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_SECOND ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_SECOND, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_SECOND;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MINUTE ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MINUTE, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_MINUTE;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_HOUR ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_HOUR, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_HOUR;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_WEEK ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_WEEK, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_WEEK;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_DAY ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_DAY, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_DAY;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_MONTH ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_MONTH, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_MONTH;
         } else if ( srcTimeUnitField == TimeUnit::UTIMEUNIT_YEAR ) {
-            messageFormat = new MessageFormat(DEFAULT_PATTERN_FOR_YEAR, fLocale, err);
+            pattern = DEFAULT_PATTERN_FOR_YEAR;
         }
-        if (U_SUCCESS(err)) {
-            if (fNumberFormat != NULL && messageFormat != NULL) {
-                messageFormat->setFormat(0, *fNumberFormat);
-            }
-            MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
-            if (formatters == NULL) {
-                formatters = (MessageFormat**)uprv_malloc(kTotal*sizeof(MessageFormat*));
-                formatters[kFull] = NULL;
-                formatters[kAbbreviate] = NULL;
-                countToPatterns->put(srcPluralCount, formatters, err);
-                if (U_FAILURE(err)) {
-                    uprv_free(formatters);
-                    delete messageFormat;
-                }
-            }
-            if (U_SUCCESS(err)) {
-                //delete formatters[style];
-                formatters[style] = messageFormat;
+        if (pattern != NULL) {
+            messageFormat.adoptInsteadAndCheckErrorCode(
+                     new MessageFormat(UnicodeString(TRUE, pattern, -1), getLocale(err), err), err);
+        }
+        if (U_FAILURE(err)) {
+            return;
+        }
+        MessageFormat** formatters = (MessageFormat**)countToPatterns->get(srcPluralCount);
+        if (formatters == NULL) {
+            LocalMemory<MessageFormat *> localFormatters (
+                    (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*)));
+            if (localFormatters.isNull()) {
+                err = U_MEMORY_ALLOCATION_ERROR;
+                return;
             }
-        } else {
-            delete messageFormat;
+            formatters = localFormatters.getAlias();
+            formatters[UTMUTFMT_FULL_STYLE] = NULL;
+            formatters[UTMUTFMT_ABBREVIATED_STYLE] = NULL;
+            countToPatterns->put(srcPluralCount, localFormatters.orphan(), err);
+        }
+        if (U_SUCCESS(err)) {
+            //delete formatters[style];
+            formatters[style] = messageFormat.orphan();
         }
     } else {
         // fall back to rule "other", and search in parents
-        searchInLocaleChain(style, key, localeName, srcTimeUnitField, srcPluralCount, 
+        searchInLocaleChain(style, key, localeName, srcTimeUnitField, srcPluralCount,
                             gPluralCountOther, countToPatterns, err);
     }
 }
 
-void 
+void
 TimeUnitFormat::setLocale(const Locale& locale, UErrorCode& status) {
-    if (U_SUCCESS(status) && fLocale != locale) {
-        fLocale = locale;
+    if (setMeasureFormatLocale(locale, status)) {
         setup(status);
     }
 }
 
 
-void 
+void
 TimeUnitFormat::setNumberFormat(const NumberFormat& format, UErrorCode& status){
-    if (U_FAILURE(status) || (fNumberFormat && format == *fNumberFormat)) {
+    if (U_FAILURE(status)) {
         return;
     }
-    delete fNumberFormat;
-    fNumberFormat = (NumberFormat*)format.clone();
-    // reset the number formatter in the fTimeUnitToCountToPatterns map
-    for (TimeUnit::UTimeUnitFields i = TimeUnit::UTIMEUNIT_YEAR;
-         i < TimeUnit::UTIMEUNIT_FIELD_COUNT;
-         i = (TimeUnit::UTimeUnitFields)(i+1)) {
-        int32_t pos = -1;
-        const UHashElement* elem = NULL;
-        while ((elem = fTimeUnitToCountToPatterns[i]->nextElement(pos)) != NULL){
-            const UHashTok keyTok = elem->value;
-            MessageFormat** pattern = (MessageFormat**)keyTok.pointer;
-            pattern[kFull]->setFormat(0, format);
-            pattern[kAbbreviate]->setFormat(0, format);
-        }
-    }
+    adoptNumberFormat((NumberFormat *)format.clone(), status);
 }
 
 
 void
 TimeUnitFormat::deleteHash(Hashtable* htable) {
-    int32_t pos = -1;
+    int32_t pos = UHASH_FIRST;
     const UHashElement* element = NULL;
     if ( htable ) {
         while ( (element = htable->nextElement(pos)) != NULL ) {
             const UHashTok valueTok = element->value;
             const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
-            delete value[kFull];
-            delete value[kAbbreviate];
+            delete value[UTMUTFMT_FULL_STYLE];
+            delete value[UTMUTFMT_ABBREVIATED_STYLE];
             //delete[] value;
             uprv_free(value);
         }
@@ -784,7 +685,7 @@ TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode&
     if ( U_FAILURE(status) ) {
         return;
     }
-    int32_t pos = -1;
+    int32_t pos = UHASH_FIRST;
     const UHashElement* element = NULL;
     if ( source ) {
         while ( (element = source->nextElement(pos)) != NULL ) {
@@ -792,7 +693,7 @@ TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode&
             const UnicodeString* key = (UnicodeString*)keyTok.pointer;
             const UHashTok valueTok = element->value;
             const MessageFormat** value = (const MessageFormat**)valueTok.pointer;
-            MessageFormat** newVal = (MessageFormat**)uprv_malloc(kTotal*sizeof(MessageFormat*));
+            MessageFormat** newVal = (MessageFormat**)uprv_malloc(UTMUTFMT_FORMAT_STYLE_COUNT*sizeof(MessageFormat*));
             newVal[0] = (MessageFormat*)value[0]->clone();
             newVal[1] = (MessageFormat*)value[1]->clone();
             target->put(UnicodeString(*key), newVal, status);
@@ -807,7 +708,7 @@ TimeUnitFormat::copyHash(const Hashtable* source, Hashtable* target, UErrorCode&
 }
 
 
-U_CDECL_BEGIN 
+U_CDECL_BEGIN
 
 /**
  * set hash table value comparator
@@ -838,7 +739,7 @@ TimeUnitFormat::initHash(UErrorCode& status) {
         return NULL;
     }
     if ( U_FAILURE(status) ) {
-        delete hTable; 
+        delete hTable;
         return NULL;
     }
     hTable->setValueComparator(tmutfmtHashTableValueComparator);
@@ -847,7 +748,7 @@ TimeUnitFormat::initHash(UErrorCode& status) {
 
 
 const char*
-TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField, 
+TimeUnitFormat::getTimeUnitName(TimeUnit::UTimeUnitFields unitField,
                                 UErrorCode& status) {
     if (U_FAILURE(status)) {
         return NULL;