import cl @80894
diff --git a/i18n/zstrfmt.cpp b/i18n/zstrfmt.cpp
index b42bbfb..79e5d76 100644
--- a/i18n/zstrfmt.cpp
+++ b/i18n/zstrfmt.cpp
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007, International Business Machines Corporation and         *
+* Copyright (C) 2007-2008, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -145,9 +145,11 @@
         case ZSIDX_LONG_DAYLIGHT:
             type = DAYLIGHT_LONG;
             break;
+        case ZSIDX_COUNT:
         case ZSIDX_SHORT_DAYLIGHT:
             type = DAYLIGHT_SHORT;
             break;
+       
     }
     return type;
 }
@@ -155,106 +157,183 @@
 #define DEFAULT_CHARACTERNODE_CAPACITY 1
 
 // ----------------------------------------------------------------------------
-CharacterNode::CharacterNode(UChar32 c, UObjectDeleter *valueDeleterFunc, UErrorCode &status)
-: UMemory(),
-  fChildren(valueDeleterFunc, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status),
-  fValues(valueDeleterFunc, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status),
-  fValueDeleter(valueDeleterFunc),
-  fCharacter(c)
-{
+void CharacterNode::clear() {
+    uprv_memset(this, 0, sizeof(*this));
 }
 
-CharacterNode::~CharacterNode() {
-    while (!fChildren.isEmpty()) {
-        CharacterNode *node = (CharacterNode*)fChildren.orphanElementAt(0);
-        delete node;
+void CharacterNode::deleteValues() {
+    if (fValues == NULL) {
+        // Do nothing.
+    } else if (!fHasValuesVector) {
+        deleteZoneStringInfo(fValues);
+    } else {
+        delete (UVector *)fValues;
     }
 }
 
 void
 CharacterNode::addValue(void *value, UErrorCode &status) {
     if (U_FAILURE(status)) {
+        deleteZoneStringInfo(value);
         return;
     }
-    fValues.addElement(value, status);
+    if (fValues == NULL) {
+        fValues = value;
+    } else {
+        // At least one value already.
+        if (!fHasValuesVector) {
+            // There is only one value so far, and not in a vector yet.
+            // Create a vector and add the old value.
+            UVector *values = new UVector(deleteZoneStringInfo, NULL, DEFAULT_CHARACTERNODE_CAPACITY, status);
+            if (U_FAILURE(status)) {
+                deleteZoneStringInfo(value);
+                return;
+            }
+            values->addElement(fValues, status);
+            fValues = values;
+            fHasValuesVector = TRUE;
+        }
+        // Add the new value.
+        ((UVector *)fValues)->addElement(value, status);
+    }
 }
 
-CharacterNode*
-CharacterNode::addChildNode(UChar32 c, UErrorCode &status) {
-    if (U_FAILURE(status)) {
-        return NULL;
-    }
-    CharacterNode *result = NULL;
-    for (int32_t i = 0; i < fChildren.size(); i++) {
-        CharacterNode *node = (CharacterNode*)fChildren.elementAt(i);
-        if (node->getCharacter() == c) {
-            result = node;
-            break;
-        }
-    }
-    if (result == NULL) {
-        result = new CharacterNode(c, fValueDeleter, status);
-        fChildren.addElement(result, status);
-    }
-
-    return result;
-}
-
-CharacterNode*
-CharacterNode::getChildNode(UChar32 c) const {
-    CharacterNode *result = NULL;
-    for (int32_t i = 0; i < fChildren.size(); i++) {
-        CharacterNode *node = (CharacterNode*)fChildren.elementAt(i);
-        if (node->getCharacter() == c) {
-            result = node;
-            break;
-        }
-    }
-    return result;
+//----------------------------------------------------------------------------
+// Virtual destructor to avoid warning
+TextTrieMapSearchResultHandler::~TextTrieMapSearchResultHandler(){
 }
 
 // ----------------------------------------------------------------------------
-TextTrieMap::TextTrieMap(UBool ignoreCase, UObjectDeleter *valueDeleterFunc)
-: UMemory(), fIgnoreCase(ignoreCase), fValueDeleter(valueDeleterFunc), fRoot(NULL) {
+TextTrieMap::TextTrieMap(UBool ignoreCase)
+: fIgnoreCase(ignoreCase), fNodes(NULL), fNodesCapacity(0), fNodesCount(0) {
 }
 
 TextTrieMap::~TextTrieMap() {
-    if (fRoot != NULL) {
-        delete fRoot;
+    int32_t index;
+    for (index = 0; index < fNodesCount; ++index) {
+        fNodes[index].deleteValues();
     }
+    uprv_free(fNodes);
 }
 
 void
 TextTrieMap::put(const UnicodeString &key, void *value, UErrorCode &status) {
-    if (fRoot == NULL) {
-        fRoot = new CharacterNode(0, fValueDeleter, status);
+    if (fNodes == NULL) {
+        fNodesCapacity = 512;
+        fNodes = (CharacterNode *)uprv_malloc(fNodesCapacity * sizeof(CharacterNode));
+        fNodes[0].clear();  // Init root node.
+        fNodesCount = 1;
     }
 
-    UnicodeString keyString(key);
+    UnicodeString foldedKey;
+    const UChar *keyBuffer;
+    int32_t keyLength;
     if (fIgnoreCase) {
-        keyString.foldCase();
+        // Ok to use fastCopyFrom() because we discard the copy when we return.
+        foldedKey.fastCopyFrom(key).foldCase();
+        keyBuffer = foldedKey.getBuffer();
+        keyLength = foldedKey.length();
+    } else {
+        keyBuffer = key.getBuffer();
+        keyLength = key.length();
     }
 
-    CharacterNode *node = fRoot;
-    int32_t index = 0;
-    while (index < keyString.length()) {
-        UChar32 c = keyString.char32At(index);
-        node = node->addChildNode(c, status);  
-        if (U_FAILURE(status)) {
-            return;
-        }
-        index = keyString.moveIndex32(index, 1);
+    CharacterNode *node = fNodes;
+    int32_t index;
+    for (index = 0; index < keyLength; ++index) {
+        node = addChildNode(node, keyBuffer[index], status);
     }
     node->addValue(value, status);
 }
 
+UBool
+TextTrieMap::growNodes() {
+    if (fNodesCapacity == 0xffff) {
+        return FALSE;  // We use 16-bit node indexes.
+    }
+    int32_t newCapacity = fNodesCapacity * 2;
+    if (newCapacity > 0xffff) {
+        newCapacity = 0xffff;
+    }
+    CharacterNode *newNodes = (CharacterNode *)uprv_malloc(newCapacity * sizeof(CharacterNode));
+    if (newNodes == NULL) {
+        return FALSE;
+    }
+    uprv_memcpy(newNodes, fNodes, fNodesCount * sizeof(CharacterNode));
+    uprv_free(fNodes);
+    fNodes = newNodes;
+    fNodesCapacity = newCapacity;
+    return TRUE;
+}
+
+CharacterNode*
+TextTrieMap::addChildNode(CharacterNode *parent, UChar c, UErrorCode &status) {
+    if (U_FAILURE(status)) {
+        return NULL;
+    }
+    // Linear search of the sorted list of children.
+    uint16_t prevIndex = 0;
+    uint16_t nodeIndex = parent->fFirstChild;
+    while (nodeIndex > 0) {
+        CharacterNode *current = fNodes + nodeIndex;
+        UChar childCharacter = current->fCharacter;
+        if (childCharacter == c) {
+            return current;
+        } else if (childCharacter > c) {
+            break;
+        }
+        prevIndex = nodeIndex;
+        nodeIndex = current->fNextSibling;
+    }
+
+    // Ensure capacity. Grow fNodes[] if needed.
+    if (fNodesCount == fNodesCapacity) {
+        int32_t parentIndex = (parent - fNodes);
+        if (!growNodes()) {
+            status = U_MEMORY_ALLOCATION_ERROR;
+            return NULL;
+        }
+        parent = fNodes + parentIndex;
+    }
+
+    // Insert a new child node with c in sorted order.
+    CharacterNode *node = fNodes + fNodesCount;
+    node->clear();
+    node->fCharacter = c;
+    node->fNextSibling = nodeIndex;
+    if (prevIndex == 0) {
+        parent->fFirstChild = (uint16_t)fNodesCount;
+    } else {
+        fNodes[prevIndex].fNextSibling = (uint16_t)fNodesCount;
+    }
+    ++fNodesCount;
+    return node;
+}
+
+CharacterNode*
+TextTrieMap::getChildNode(CharacterNode *parent, UChar c) const {
+    // Linear search of the sorted list of children.
+    uint16_t nodeIndex = parent->fFirstChild;
+    while (nodeIndex > 0) {
+        CharacterNode *current = fNodes + nodeIndex;
+        UChar childCharacter = current->fCharacter;
+        if (childCharacter == c) {
+            return current;
+        } else if (childCharacter > c) {
+            break;
+        }
+        nodeIndex = current->fNextSibling;
+    }
+    return NULL;
+}
+
 void
 TextTrieMap::search(const UnicodeString &text, int32_t start,
                   TextTrieMapSearchResultHandler *handler, UErrorCode &status) const {
-    if (fRoot == NULL) {
+    if (fNodes == NULL) {
         return;
     }
-    search(fRoot, text, start, start, handler, status);
+    search(fNodes, text, start, start, handler, status);
 }
 
 void
@@ -263,9 +342,8 @@
     if (U_FAILURE(status)) {
         return;
     }
-    const UVector *values = node->getValues();
-    if (values != NULL) {
-        if (!handler->handleMatch(index - start, values, status)) {
+    if (node->hasValues()) {
+        if (!handler->handleMatch(index - start, node, status)) {
             return;
         }
         if (U_FAILURE(status)) {
@@ -280,14 +358,14 @@
         int32_t tmpidx = 0;
         while (tmpidx < tmp.length()) {
             c = tmp.char32At(tmpidx);
-            node = node->getChildNode(c);
+            node = getChildNode(node, c);
             if (node == NULL) {
                 break;
             }
             tmpidx = tmp.moveIndex32(tmpidx, 1);
         }
     } else {
-        node = node->getChildNode(c);
+        node = getChildNode(node, c);
     }
     if (node != NULL) {
         search(node, text, start, index+1, handler, status);
@@ -297,14 +375,14 @@
 // ----------------------------------------------------------------------------
 ZoneStringInfo::ZoneStringInfo(const UnicodeString &id, const UnicodeString &str,
                                TimeZoneTranslationType type)
-: UMemory(), fId(id), fStr(str), fType(type) {
+: fId(id), fStr(str), fType(type) {
 }
 
 ZoneStringInfo::~ZoneStringInfo() {
 }
 // ----------------------------------------------------------------------------
 ZoneStringSearchResultHandler::ZoneStringSearchResultHandler(UErrorCode &status)
-: UMemory(), fResults(status)
+: fResults(status)
 {
     clear();
 }
@@ -314,13 +392,14 @@
 }
 
 UBool
-ZoneStringSearchResultHandler::handleMatch(int32_t matchLength, const UVector *values, UErrorCode &status) {
+ZoneStringSearchResultHandler::handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status) {
     if (U_FAILURE(status)) {
         return FALSE;
     }
-    if (values != NULL) {
-        for (int32_t i = 0; values->size(); i++) {
-            ZoneStringInfo *zsinfo = (ZoneStringInfo*)values->elementAt(i);
+    if (node->hasValues()) {
+        int32_t valuesCount = node->countValues();
+        for (int32_t i = 0; i < valuesCount; i++) {
+            ZoneStringInfo *zsinfo = (ZoneStringInfo*)node->getValue(i);
             if (zsinfo == NULL) {
                 break;
             }
@@ -374,11 +453,10 @@
 // ----------------------------------------------------------------------------
 ZoneStringFormat::ZoneStringFormat(const UnicodeString* const* strings,
                                    int32_t rowCount, int32_t columnCount, UErrorCode &status)
-: UMemory(),
-  fLocale(""),
+: fLocale(""),
   fTzidToStrings(uhash_compareUnicodeString, NULL, status),
   fMzidToStrings(uhash_compareUnicodeString, NULL, status),
-  fZoneStringsTrie(TRUE, deleteZoneStringInfo)
+  fZoneStringsTrie(TRUE)
 {
     if (U_FAILURE(status)) {
         return;
@@ -450,11 +528,10 @@
 }
 
 ZoneStringFormat::ZoneStringFormat(const Locale &locale, UErrorCode &status)
-: UMemory(),
-  fLocale(locale),
+: fLocale(locale),
   fTzidToStrings(uhash_compareUnicodeString, NULL, status),
   fMzidToStrings(uhash_compareUnicodeString, NULL, status),
-  fZoneStringsTrie(TRUE, deleteZoneStringInfo)
+  fZoneStringsTrie(TRUE)
 {
     if (U_FAILURE(status)) {
         return;
@@ -647,8 +724,7 @@
                                 ZoneStringInfo *zsinfo = new ZoneStringInfo(preferredIdForLocale, strings_mz[typeidx], (TimeZoneTranslationType)type);
                                 fZoneStringsTrie.put(strings_mz[typeidx], zsinfo, status);
                                 if (U_FAILURE(status)) {
-                                    delete zsinfo;
-                                    delete strings_mz;
+                                    delete []strings_mz;
                                     goto error_cleanup;
                                 }
                             }
@@ -661,7 +737,6 @@
 
                     fMzidToStrings.put(mzid, tmp_mzStrings, status);
                     if (U_FAILURE(status)) {
-                        delete tmp_mzStrings;
                         goto error_cleanup;
                     }
 
@@ -987,6 +1062,7 @@
 
     // ICU's own array does not have entries for aliases
     UnicodeString canonicalID;
+    UErrorCode status = U_ZERO_ERROR;
     ZoneMeta::getCanonicalID(tzid, canonicalID);
 
     if (fTzidToStrings.count() > 0) {
@@ -1001,6 +1077,7 @@
                     break;
                 case ZSIDX_SHORT_STANDARD:
                 case ZSIDX_SHORT_DAYLIGHT:
+                case ZSIDX_COUNT: //added to avoid warning
                 case ZSIDX_SHORT_GENERIC:
                     if (!commonlyUsedOnly || zstrings->isShortFormatCommonlyUsed()) {
                         zstrings->getString(typeIdx, result);
@@ -1025,6 +1102,7 @@
                         break;
                     case ZSIDX_SHORT_STANDARD:
                     case ZSIDX_SHORT_DAYLIGHT:
+                    case ZSIDX_COUNT: //added to avoid warning
                     case ZSIDX_SHORT_GENERIC:
                         if (!commonlyUsedOnly || mzstrings->isShortFormatCommonlyUsed()) {
                             mzstrings->getString(typeIdx, result);
@@ -1053,7 +1131,7 @@
     UnicodeString canonicalID;
     ZoneMeta::getCanonicalID(tzid, canonicalID);
 
-    ZoneStrings *zstrings;
+    ZoneStrings *zstrings = NULL;
     if (fTzidToStrings.count() > 0) {
         zstrings = (ZoneStrings*)fTzidToStrings.get(canonicalID);
         if (zstrings != NULL) {
@@ -1205,6 +1283,7 @@
     }
 
     UnicodeString canonicalID;
+    UErrorCode status = U_ZERO_ERROR;
     ZoneMeta::getCanonicalID(tzid, canonicalID);
 
     UnicodeString mzid;
@@ -1397,7 +1476,7 @@
  */
 ZoneStrings::ZoneStrings(UnicodeString *strings, int32_t stringsCount, UBool commonlyUsed,
        UnicodeString **genericPartialLocationStrings, int32_t genericRowCount, int32_t genericColCount)
-: UMemory(), fStrings(strings), fStringsCount(stringsCount), fIsCommonlyUsed(commonlyUsed),
+: fStrings(strings), fStringsCount(stringsCount), fIsCommonlyUsed(commonlyUsed),
   fGenericPartialLocationStrings(genericPartialLocationStrings), 
   fGenericPartialLocationRowCount(genericRowCount), fGenericPartialLocationColCount(genericColCount) {
 }
@@ -1456,7 +1535,7 @@
 
 // --------------------------------------------------------------
 SafeZoneStringFormatPtr::SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry)
-: UMemory(), fCacheEntry(cacheEntry) {
+: fCacheEntry(cacheEntry) {
 }
 
 SafeZoneStringFormatPtr::~SafeZoneStringFormatPtr() {
@@ -1469,7 +1548,7 @@
 }
 
 ZSFCacheEntry::ZSFCacheEntry(const Locale &locale, ZoneStringFormat *zsf, ZSFCacheEntry *next)
-: UMemory(), fLocale(locale), fZoneStringFormat(zsf),
+: fLocale(locale), fZoneStringFormat(zsf),
  fNext(next), fRefCount(1)
 {
 }
@@ -1491,7 +1570,7 @@
 }
 
 ZSFCache::ZSFCache(int32_t capacity)
-: UMemory(), fCapacity(capacity), fFirst(NULL) {
+: fCapacity(capacity), fFirst(NULL) {
 }
 
 ZSFCache::~ZSFCache() {
@@ -1537,6 +1616,11 @@
     if (entry == NULL) {
         ZoneStringFormat *zsf = new ZoneStringFormat(locale, status);
         if (U_FAILURE(status)) {
+            delete zsf;
+            return NULL;
+        }
+        if (zsf == NULL) {
+            status = U_MEMORY_ALLOCATION_ERROR;
             return NULL;
         }
         // Now add the new entry
diff --git a/i18n/zstrfmt.h b/i18n/zstrfmt.h
index 6765d6d..bbc5c9b 100644
--- a/i18n/zstrfmt.h
+++ b/i18n/zstrfmt.h
@@ -1,6 +1,6 @@
 /*
 *******************************************************************************
-* Copyright (C) 2007, International Business Machines Corporation and         *
+* Copyright (C) 2007-2008, International Business Machines Corporation and    *
 * others. All Rights Reserved.                                                *
 *******************************************************************************
 */
@@ -21,45 +21,58 @@
 /*
  * Character node used by TextTrieMap
  */
-class CharacterNode : public UMemory {
-public:
-    CharacterNode(UChar32 c, UObjectDeleter *fn, UErrorCode &status);
-    virtual ~CharacterNode();
+struct CharacterNode {
+    // No constructor or destructor.
+    // We malloc and free an uninitalized array of CharacterNode objects
+    // and clear and delete them ourselves.
 
-    inline UChar32 getCharacter(void) const;
-    inline const UVector* getValues(void) const;
-    inline const UVector* getChildNodes(void) const;
+    void clear();
+    void deleteValues();
 
     void addValue(void *value, UErrorCode &status);
-    CharacterNode* addChildNode(UChar32 c, UErrorCode &status);
-    CharacterNode* getChildNode(UChar32 c) const;
+    inline UBool hasValues() const;
+    inline int32_t countValues() const;
+    inline const void *getValue(int32_t index) const;
 
-private:
-    UVector fChildren;
-    UVector fValues;
-    UObjectDeleter  *fValueDeleter;
-    UChar32 fCharacter;
+    void     *fValues;      // Union of one single value vs. UVector of values.
+    UChar    fCharacter;    // UTF-16 code unit.
+    uint16_t fFirstChild;   // 0 if no children.
+    uint16_t fNextSibling;  // 0 terminates the list.
+    UBool    fHasValuesVector;
+    UBool    fPadding;
+
+    // No value:   fValues == NULL               and  fHasValuesVector == FALSE
+    // One value:  fValues == value              and  fHasValuesVector == FALSE
+    // >=2 values: fValues == UVector of values  and  fHasValuesVector == TRUE
 };
 
-inline UChar32 CharacterNode::getCharacter(void) const {
-    return fCharacter;
+inline UBool CharacterNode::hasValues() const {
+    return (UBool)(fValues != NULL);
 }
 
-inline const UVector* CharacterNode::getValues(void) const {
-    return &fValues;
+inline int32_t CharacterNode::countValues() const {
+    return
+        fValues == NULL ? 0 :
+        !fHasValuesVector ? 1 :
+        ((const UVector *)fValues)->size();
 }
 
-inline const UVector* CharacterNode::getChildNodes(void) const {
-    return &fChildren;
+inline const void *CharacterNode::getValue(int32_t index) const {
+    if (!fHasValuesVector) {
+        return fValues;  // Assume index == 0.
+    } else {
+        return ((const UVector *)fValues)->elementAt(index);
+    }
 }
 
 /*
  * Search result handler callback interface used by TextTrieMap search.
  */
-class TextTrieMapSearchResultHandler {
+class TextTrieMapSearchResultHandler : public UMemory {
 public:
     virtual UBool handleMatch(int32_t matchLength,
-        const UVector *values, UErrorCode& status) = 0;
+                              const CharacterNode *node, UErrorCode& status) = 0;
+    virtual ~TextTrieMapSearchResultHandler(); //added to avoid warning
 };
 
 /**
@@ -68,7 +81,7 @@
  */
 class TextTrieMap : public UMemory {
 public:
-    TextTrieMap(UBool ignoreCase, UObjectDeleter *valueDeleterFunc);
+    TextTrieMap(UBool ignoreCase);
     virtual ~TextTrieMap();
 
     void put(const UnicodeString &key, void *value, UErrorCode &status);
@@ -78,15 +91,20 @@
 
 private:
     UBool           fIgnoreCase;
-    UObjectDeleter  *fValueDeleter;
-    CharacterNode   *fRoot;
+    CharacterNode   *fNodes;
+    int32_t         fNodesCapacity;
+    int32_t         fNodesCount;
+
+    UBool growNodes();
+    CharacterNode* addChildNode(CharacterNode *parent, UChar c, UErrorCode &status);
+    CharacterNode* getChildNode(CharacterNode *parent, UChar c) const;
 
     void search(CharacterNode *node, const UnicodeString &text, int32_t start,
         int32_t index, TextTrieMapSearchResultHandler *handler, UErrorCode &status) const;
 };
 
 inline UChar32 TextTrieMap::isEmpty(void) const {
-    return fRoot == NULL;
+    return fNodes == NULL;
 }
 
 // Name types, these bit flag are used for zone string lookup
@@ -373,12 +391,12 @@
  * TextTrieMapSearchHandler.  This class is used by ZoneStringFormat
  * for collecting search results for localized zone strings.
  */
-class ZoneStringSearchResultHandler : public UMemory, TextTrieMapSearchResultHandler {
+class ZoneStringSearchResultHandler : public TextTrieMapSearchResultHandler {
 public:
     ZoneStringSearchResultHandler(UErrorCode &status);
     virtual ~ZoneStringSearchResultHandler();
 
-    virtual UBool handleMatch(int32_t matchLength, const UVector *values, UErrorCode &status);
+    virtual UBool handleMatch(int32_t matchLength, const CharacterNode *node, UErrorCode &status);
     int32_t countMatches(void);
     const ZoneStringInfo* getMatch(int32_t index, int32_t &matchLength);
     void clear(void);