aboutsummaryrefslogtreecommitdiff
path: root/i18n
diff options
context:
space:
mode:
authorJean-Baptiste Queru <jbq@google.com>2009-07-17 17:59:18 -0700
committerJean-Baptiste Queru <jbq@google.com>2009-07-17 17:59:18 -0700
commit072a5238ae2b3c25cf72bead1dbb1026de054103 (patch)
tree4b884c484184c7d9b8543b697b7a5f091873dd5c /i18n
parent037e0a44b2bb27f80aab2556d41e26bdb2aafcd7 (diff)
downloadicu4c-072a5238ae2b3c25cf72bead1dbb1026de054103.tar.gz
import cl @80894
Diffstat (limited to 'i18n')
-rw-r--r--i18n/zstrfmt.cpp258
-rw-r--r--i18n/zstrfmt.h78
2 files changed, 219 insertions, 117 deletions
diff --git a/i18n/zstrfmt.cpp b/i18n/zstrfmt.cpp
index b42bbfb2..79e5d768 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 @@ getTimeZoneTranslationType(TimeZoneTranslationTypeIndex typeIdx) {
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 @@ getTimeZoneTranslationType(TimeZoneTranslationTypeIndex typeIdx) {
#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);
-}
-
-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 (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);
}
- 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 @@ TextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t star
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 @@ TextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t star
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 @@ TextTrieMap::search(CharacterNode *node, const UnicodeString &text, int32_t star
// ----------------------------------------------------------------------------
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 @@ ZoneStringSearchResultHandler::~ZoneStringSearchResultHandler() {
}
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 @@ ZoneStringSearchResultHandler::clear(void) {
// ----------------------------------------------------------------------------
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 @@ error_cleanup:
}
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 @@ ZoneStringFormat::ZoneStringFormat(const Locale &locale, UErrorCode &status)
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 @@ ZoneStringFormat::ZoneStringFormat(const Locale &locale, UErrorCode &status)
fMzidToStrings.put(mzid, tmp_mzStrings, status);
if (U_FAILURE(status)) {
- delete tmp_mzStrings;
goto error_cleanup;
}
@@ -987,6 +1062,7 @@ ZoneStringFormat::getString(const UnicodeString &tzid, TimeZoneTranslationTypeIn
// 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 @@ ZoneStringFormat::getString(const UnicodeString &tzid, TimeZoneTranslationTypeIn
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 @@ ZoneStringFormat::getString(const UnicodeString &tzid, TimeZoneTranslationTypeIn
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 @@ ZoneStringFormat::getGenericString(const Calendar &cal, UBool isShort, UBool com
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 @@ ZoneStringFormat::getGenericPartialLocationString(const UnicodeString &tzid, UBo
}
UnicodeString canonicalID;
+ UErrorCode status = U_ZERO_ERROR;
ZoneMeta::getCanonicalID(tzid, canonicalID);
UnicodeString mzid;
@@ -1397,7 +1476,7 @@ ZoneStringFormat::getLocalizedCountry(const UnicodeString &countryCode, const Lo
*/
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 @@ ZoneStrings::getGenericPartialLocationString(const UnicodeString &mzid, UBool is
// --------------------------------------------------------------
SafeZoneStringFormatPtr::SafeZoneStringFormatPtr(ZSFCacheEntry *cacheEntry)
-: UMemory(), fCacheEntry(cacheEntry) {
+: fCacheEntry(cacheEntry) {
}
SafeZoneStringFormatPtr::~SafeZoneStringFormatPtr() {
@@ -1469,7 +1548,7 @@ SafeZoneStringFormatPtr::get() const {
}
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 @@ ZSFCacheEntry::delRef(void) {
}
ZSFCache::ZSFCache(int32_t capacity)
-: UMemory(), fCapacity(capacity), fFirst(NULL) {
+: fCapacity(capacity), fFirst(NULL) {
}
ZSFCache::~ZSFCache() {
@@ -1537,6 +1616,11 @@ ZSFCache::get(const Locale &locale, UErrorCode &status) {
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 6765d6dd..bbc5c9be 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 @@ U_NAMESPACE_BEGIN
/*
* 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;
-
-private:
- UVector fChildren;
- UVector fValues;
- UObjectDeleter *fValueDeleter;
- UChar32 fCharacter;
+ inline UBool hasValues() const;
+ inline int32_t countValues() const;
+ inline const void *getValue(int32_t index) const;
+
+ 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 @@ public:
*/
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 @@ public:
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 @@ ZoneStrings::isShortFormatCommonlyUsed(void) const {
* 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);