ICU-11389 improve error checking

X-SVN-Rev: 36758
This commit is contained in:
Steven R. Loomis 2014-11-20 00:34:29 +00:00
parent 9edbbecb24
commit 738cee69cc
6 changed files with 113 additions and 83 deletions

View File

@ -25,6 +25,7 @@
#include "unicode/ures.h" #include "unicode/ures.h"
#include "unicode/ustring.h" #include "unicode/ustring.h"
#include "unicode/rep.h" #include "unicode/rep.h"
#include "uassert.h"
#include "cpputils.h" #include "cpputils.h"
#include "mutex.h" #include "mutex.h"
#include "cmemory.h" #include "cmemory.h"
@ -430,7 +431,7 @@ DateTimePatternGenerator::initData(const Locale& locale, UErrorCode &status) {
skipMatcher = NULL; skipMatcher = NULL;
fAvailableFormatKeyHash=NULL; fAvailableFormatKeyHash=NULL;
addCanonicalItems(); addCanonicalItems(status);
addICUPatterns(locale, status); addICUPatterns(locale, status);
if (U_FAILURE(status)) { if (U_FAILURE(status)) {
return; return;
@ -554,8 +555,6 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, UPRV_LENGTHOF(UDATPG_ItemFormat)-1); // Read-only alias. UnicodeString defaultItemFormat(TRUE, UDATPG_ItemFormat, UPRV_LENGTHOF(UDATPG_ItemFormat)-1); // Read-only alias.
err = U_ZERO_ERROR;
fDefaultHourFormatChar = 0; fDefaultHourFormatChar = 0;
for (i=0; i<UDATPG_FIELD_COUNT; ++i ) { for (i=0; i<UDATPG_FIELD_COUNT; ++i ) {
appendItemNames[i]=CAP_F; appendItemNames[i]=CAP_F;
@ -584,11 +583,11 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
"calendar", "calendar", locale.getName(), NULL, FALSE, &err); "calendar", "calendar", locale.getName(), NULL, FALSE, &err);
localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination localeWithCalendarKey[ULOC_LOCALE_IDENTIFIER_CAPACITY-1] = 0; // ensure null termination
// now get the calendar key value from that locale // now get the calendar key value from that locale
int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &err); UErrorCode err2 = err;
if (U_SUCCESS(err) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) { int32_t calendarTypeLen = uloc_getKeywordValue(localeWithCalendarKey, "calendar", calendarType, ULOC_KEYWORDS_CAPACITY, &err2);
if (U_SUCCESS(err2) && calendarTypeLen < ULOC_KEYWORDS_CAPACITY) {
calendarTypeToUse = calendarType; calendarTypeToUse = calendarType;
} }
err = U_ZERO_ERROR;
} }
calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err); calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err);
calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err); calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err);
@ -596,103 +595,111 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
key=NULL; key=NULL;
int32_t dtCount=0; int32_t dtCount=0;
patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimePatternsTag, NULL, &err); patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimePatternsTag, NULL, &err);
while (U_SUCCESS(err)) { {
rbPattern = ures_getNextUnicodeString(patBundle, &key, &err); UErrorCode err2 = err;
while (U_SUCCESS(err2)) {
rbPattern = ures_getNextUnicodeString(patBundle, &key, &err2);
dtCount++; dtCount++;
if (rbPattern.length()==0 ) { if (rbPattern.length()==0 ) {
break; // no more pattern break; // no more pattern
} }
else { else {
if (dtCount==9) { if (dtCount==9) {
setDateTimeFormat(rbPattern); setDateTimeFormat(rbPattern);
} else if (dtCount==4) { // short time format } else if (dtCount==4) { // short time format
// set fDefaultHourFormatChar to the hour format character from this pattern // set fDefaultHourFormatChar to the hour format character from this pattern
int32_t tfIdx, tfLen = rbPattern.length(); int32_t tfIdx, tfLen = rbPattern.length();
UBool ignoreChars = FALSE; UBool ignoreChars = FALSE;
for (tfIdx = 0; tfIdx < tfLen; tfIdx++) { for (tfIdx = 0; tfIdx < tfLen; tfIdx++) {
UChar tfChar = rbPattern.charAt(tfIdx); UChar tfChar = rbPattern.charAt(tfIdx);
if ( tfChar == SINGLE_QUOTE ) { if ( tfChar == SINGLE_QUOTE ) {
ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote) ignoreChars = !ignoreChars; // toggle (handle quoted literals & '' for single quote)
} else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) { } else if ( !ignoreChars && u_strchr(hourFormatChars, tfChar) != NULL ) {
fDefaultHourFormatChar = tfChar; fDefaultHourFormatChar = tfChar;
break; break;
} }
} }
} }
} }
} }
ures_close(patBundle); ures_close(patBundle);
err = U_ZERO_ERROR; }
patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAppendItemsTag, NULL, &err); {
key=NULL; UErrorCode err2 = err;
UnicodeString itemKey; patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAppendItemsTag, NULL, &err2);
while (U_SUCCESS(err)) { key=NULL;
rbPattern = ures_getNextUnicodeString(patBundle, &key, &err); UnicodeString itemKey;
while (U_SUCCESS(err2)) {
rbPattern = ures_getNextUnicodeString(patBundle, &key, &err2);
if (rbPattern.length()==0 ) { if (rbPattern.length()==0 ) {
break; // no more pattern break; // no more pattern
} }
else { else {
setAppendItemFormat(getAppendFormatNumber(key), rbPattern); setAppendItemFormat(getAppendFormatNumber(key), rbPattern);
} }
}
} }
ures_close(patBundle); ures_close(patBundle);
key=NULL; key=NULL;
err = U_ZERO_ERROR; {
fBundle = ures_getByKeyWithFallback(rb, DT_DateTimeFieldsTag, NULL, &err); UErrorCode err2 = err;
for (i=0; i<MAX_RESOURCE_FIELD; ++i) { fBundle = ures_getByKeyWithFallback(rb, DT_DateTimeFieldsTag, NULL, &err2);
err = U_ZERO_ERROR; for (i=0; i<MAX_RESOURCE_FIELD; ++i) {
patBundle = ures_getByKeyWithFallback(fBundle, Resource_Fields[i], NULL, &err); UErrorCode err3 = err2;
fieldBundle = ures_getByKeyWithFallback(patBundle, "dn", NULL, &err); patBundle = ures_getByKeyWithFallback(fBundle, Resource_Fields[i], NULL, &err3);
rbPattern = ures_getNextUnicodeString(fieldBundle, &key, &err); fieldBundle = ures_getByKeyWithFallback(patBundle, "dn", NULL, &err3);
rbPattern = ures_getNextUnicodeString(fieldBundle, &key, &err3);
ures_close(fieldBundle); ures_close(fieldBundle);
ures_close(patBundle); ures_close(patBundle);
if (rbPattern.length()==0 ) { if (U_FAILURE(err3) || rbPattern.length()==0 ) {
continue; continue;
} }
else { else {
setAppendItemName(getAppendNameNumber(Resource_Fields[i]), rbPattern); setAppendItemName(getAppendNameNumber(Resource_Fields[i]), rbPattern);
} }
}
ures_close(fBundle);
} }
ures_close(fBundle);
// add available formats // add available formats
UBool firstTimeThrough = TRUE; UBool firstTimeThrough = TRUE;
err = U_ZERO_ERROR;
initHashtable(err); initHashtable(err);
UBool override = TRUE; UBool override = TRUE;
while (TRUE) { {
while (TRUE) {
UErrorCode err2 = err;
// At the start of the loop: // At the start of the loop:
// - rb is the open resource bundle for the current locale being processed, // - rb is the open resource bundle for the current locale being processed,
// whose actual name is in curLocaleName. // whose actual name is in curLocaleName.
// - if U_SUCCESS(err), then calBundle and calTypeBundle are open; // - if U_SUCCESS(err), then calBundle and calTypeBundle are open;
// process contents of calTypeBundle, then close calBundle and calTypeBundle. // process contents of calTypeBundle, then close calBundle and calTypeBundle.
if (U_SUCCESS(err)) { if (U_SUCCESS(err2)) {
// process contents of calTypeBundle // process contents of calTypeBundle
patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAvailableFormatsTag, NULL, &err); patBundle = ures_getByKeyWithFallback(calTypeBundle, DT_DateTimeAvailableFormatsTag, NULL, &err2);
if (U_SUCCESS(err)) { if (U_SUCCESS(err2)) {
int32_t numberKeys = ures_getSize(patBundle); int32_t numberKeys = ures_getSize(patBundle);
int32_t len; int32_t len;
const UChar *retPattern; const UChar *retPattern;
key=NULL; key=NULL;
#if defined(U_USE_ASCII_BUNDLE_ITERATOR) #if defined(U_USE_ASCII_BUNDLE_ITERATOR)
UResourceBundleAIterator aiter; UResourceBundleAIterator aiter;
ures_a_open(&aiter, patBundle, &err); ures_a_open(&aiter, patBundle, &err2);
#endif #endif
for(i=0; i<numberKeys; ++i) { for(i=0; i<numberKeys; ++i) {
#if defined(U_USE_ASCII_BUNDLE_ITERATOR) #if defined(U_USE_ASCII_BUNDLE_ITERATOR)
retPattern=ures_a_getNextString(&aiter, &len, &key, &err); retPattern=ures_a_getNextString(&aiter, &len, &key, &err2);
#else #else
retPattern=ures_getNextString(patBundle, &len, &key, &err); retPattern=ures_getNextString(patBundle, &len, &key, &err);
#endif #endif
UnicodeString format=UnicodeString(retPattern); UnicodeString format=UnicodeString(retPattern);
UnicodeString retKey=UnicodeString(key, -1, US_INV); UnicodeString retKey=UnicodeString(key, -1, US_INV);
if ( firstTimeThrough || !isAvailableFormatSet(retKey) ) { if ( firstTimeThrough || !isAvailableFormatSet(retKey) ) {
setAvailableFormat(retKey, err); setAvailableFormat(retKey, err2);
// Add pattern with its associated skeleton. Override any duplicate derived from std patterns, // Add pattern with its associated skeleton. Override any duplicate derived from std patterns,
// but not a previous availableFormats entry: // but not a previous availableFormats entry:
addPatternWithSkeleton(format, &retKey, override, conflictingPattern, err); addPatternWithSkeleton(format, &retKey, override, conflictingPattern, err2);
} }
} }
#if defined(U_USE_ASCII_BUNDLE_ITERATOR) #if defined(U_USE_ASCII_BUNDLE_ITERATOR)
@ -713,32 +720,31 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
// Find the name of the appropriate parent locale (from %%Parent if present, else // Find the name of the appropriate parent locale (from %%Parent if present, else
// uloc_getParent on the actual locale name) // uloc_getParent on the actual locale name)
// (It would be nice to have a ures function that did this...) // (It would be nice to have a ures function that did this...)
err = U_ZERO_ERROR; UErrorCode err3 = err2;
char parentLocale[ULOC_FULLNAME_CAPACITY]; char parentLocale[ULOC_FULLNAME_CAPACITY];
int32_t locNameLen; int32_t locNameLen;
const UChar * parentUName = ures_getStringByKey(rb, "%%Parent", &locNameLen, &err); if(U_SUCCESS(err3)) err3 = U_ZERO_ERROR; // warning sensitive code
if (U_SUCCESS(err) && err != U_USING_FALLBACK_WARNING && locNameLen < ULOC_FULLNAME_CAPACITY) { const UChar * parentUName = ures_getStringByKey(rb, "%%Parent", &locNameLen, &err3);
if (U_SUCCESS(err3) && err3 != U_USING_FALLBACK_WARNING && locNameLen < ULOC_FULLNAME_CAPACITY) {
u_UCharsToChars(parentUName, parentLocale, locNameLen + 1); u_UCharsToChars(parentUName, parentLocale, locNameLen + 1);
} else { } else {
err = U_ZERO_ERROR; UErrorCode err4 = err2;
uloc_getParent(curLocaleName, parentLocale, ULOC_FULLNAME_CAPACITY, &err); uloc_getParent(curLocaleName, parentLocale, ULOC_FULLNAME_CAPACITY, &err4);
if (U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) { if (U_FAILURE(err4) || err4 == U_STRING_NOT_TERMINATED_WARNING) {
// just fallback to root, since we are not already there // just fallback to root, since we are not already there
parentLocale[0] = 0; parentLocale[0] = 0;
err = U_ZERO_ERROR; }
}
} }
// Close current locale bundle // Close current locale bundle
ures_close(rb); ures_close(rb);
// And open its parent, which becomes the new current locale being processed // And open its parent, which becomes the new current locale being processed
rb = ures_open(NULL, parentLocale, &err); rb = ures_open(NULL, parentLocale, &err2);
if ( U_FAILURE(err) ) { if ( U_FAILURE(err2) ) {
err = U_ZERO_ERROR; break;
break;
} }
// Get the name of the parent / new current locale // Get the name of the parent / new current locale
curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &err); curLocaleName=ures_getLocaleByType(rb, ULOC_ACTUAL_LOCALE, &err2);
if ( U_FAILURE(err) ) { if ( U_FAILURE(err2) ) {
curLocaleName = parentLocale; curLocaleName = parentLocale;
err = U_ZERO_ERROR; err = U_ZERO_ERROR;
} }
@ -746,15 +752,16 @@ DateTimePatternGenerator::addCLDRData(const Locale& locale, UErrorCode& err) {
override = FALSE; override = FALSE;
} }
// Open calBundle and calTypeBundle // Open calBundle and calTypeBundle
calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err); calBundle = ures_getByKeyWithFallback(rb, DT_DateTimeCalendarTag, NULL, &err2);
if (U_SUCCESS(err)) { if (U_SUCCESS(err2)) {
calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err); calTypeBundle = ures_getByKeyWithFallback(calBundle, calendarTypeToUse, NULL, &err2);
if ( U_FAILURE(err) ) { if ( U_FAILURE(err2) ) {
ures_close(calBundle); ures_close(calBundle);
} }
} }
// Go to the top of the loop to process contents of calTypeBundle // Go to the top of the loop to process contents of calTypeBundle
} }
}
if (hackPattern.length()>0) { if (hackPattern.length()>0) {
hackTimes(hackPattern, err); hackTimes(hackPattern, err);
@ -900,10 +907,8 @@ DateTimePatternGenerator::getDecimal() const {
} }
void void
DateTimePatternGenerator::addCanonicalItems() { DateTimePatternGenerator::addCanonicalItems(UErrorCode &status) {
UnicodeString conflictingPattern; UnicodeString conflictingPattern;
UErrorCode status = U_ZERO_ERROR;
for (int32_t i=0; i<UDATPG_FIELD_COUNT; i++) { for (int32_t i=0; i<UDATPG_FIELD_COUNT; i++) {
addPattern(UnicodeString(Canonical_Items[i]), FALSE, conflictingPattern, status); addPattern(UnicodeString(Canonical_Items[i]), FALSE, conflictingPattern, status);
} }
@ -1947,12 +1952,10 @@ PatternMapIterator::PatternMapIterator() {
bootIndex = 0; bootIndex = 0;
nodePtr = NULL; nodePtr = NULL;
patternMap=NULL; patternMap=NULL;
matcher= new DateTimeMatcher();
} }
PatternMapIterator::~PatternMapIterator() { PatternMapIterator::~PatternMapIterator() {
delete matcher;
} }
void void
@ -2029,12 +2032,12 @@ PatternMapIterator::next() {
} }
} }
if (nodePtr!=NULL) { if (nodePtr!=NULL) {
matcher->copyFrom(*nodePtr->skeleton); matcher.copyFrom(*nodePtr->skeleton);
} }
else { else {
matcher->copyFrom(); matcher.copyFrom();
} }
return *matcher; return matcher;
} }
PtnSkeleton::PtnSkeleton() { PtnSkeleton::PtnSkeleton() {

View File

@ -1,6 +1,6 @@
/* /*
******************************************************************************* *******************************************************************************
* Copyright (C) 2007-2013, International Business Machines Corporation and * Copyright (C) 2007-2014, International Business Machines Corporation and
* others. All Rights Reserved. * * others. All Rights Reserved. *
******************************************************************************* *******************************************************************************
* *
@ -212,10 +212,10 @@ private:
PtnElem* getDuplicateElem(const UnicodeString &basePattern, const PtnSkeleton& skeleton, PtnElem *baseElem); PtnElem* getDuplicateElem(const UnicodeString &basePattern, const PtnSkeleton& skeleton, PtnElem *baseElem);
}; // end PatternMap }; // end PatternMap
class PatternMapIterator : public UMemory { class PatternMapIterator {
public: public:
PatternMapIterator(); PatternMapIterator();
virtual ~PatternMapIterator(); ~PatternMapIterator();
void set(PatternMap& patternMap); void set(PatternMap& patternMap);
PtnSkeleton* getSkeleton(); PtnSkeleton* getSkeleton();
UBool hasNext(); UBool hasNext();
@ -223,7 +223,7 @@ public:
private: private:
int32_t bootIndex; int32_t bootIndex;
PtnElem *nodePtr; PtnElem *nodePtr;
DateTimeMatcher *matcher; DateTimeMatcher matcher;
PatternMap *patternMap; PatternMap *patternMap;
}; };

View File

@ -132,12 +132,13 @@ void Region::loadRegionData(UErrorCode &status) {
while ( ures_hasNext(regionCodes.getAlias()) ) { while ( ures_hasNext(regionCodes.getAlias()) ) {
UnicodeString regionID = ures_getNextUnicodeString(regionCodes.getAlias(), NULL, &status); UnicodeString regionID = ures_getNextUnicodeString(regionCodes.getAlias(), NULL, &status);
Region *r = new Region(); LocalPointer<Region> r(new Region, status);
if(U_FAILURE(status)) return;
r->idStr = regionID; r->idStr = regionID;
r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV); r->idStr.extract(0,r->idStr.length(),r->id,sizeof(r->id),US_INV);
r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known. r->type = URGN_TERRITORY; // Only temporary - figure out the real type later once the aliases are known.
uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r,&status); uhash_put(regionIDMap,(void *)&(r->idStr),(void *)r.orphan(),&status);
Formattable result; Formattable result;
UErrorCode ps = U_ZERO_ERROR; UErrorCode ps = U_ZERO_ERROR;
df->parse(r->idStr,result,ps); df->parse(r->idStr,result,ps);
@ -167,6 +168,12 @@ void Region::loadRegionData(UErrorCode &status) {
} else { } else {
if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it. if ( aliasFromRegion == NULL ) { // Deprecated region code not in the master codes list - so need to create a deprecated region for it.
aliasFromRegion = new Region(); aliasFromRegion = new Region();
if ( aliasFromRegion == NULL ) {
if ( U_SUCCESS(status) ) {
status = U_MEMORY_ALLOCATION_ERROR;
}
return;
}
aliasFromRegion->idStr.setTo(*aliasFromStr); aliasFromRegion->idStr.setTo(*aliasFromStr);
aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV); aliasFromRegion->idStr.extract(0,aliasFromRegion->idStr.length(),aliasFromRegion->id,sizeof(aliasFromRegion->id),US_INV);
uhash_put(regionIDMap,(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status); uhash_put(regionIDMap,(void *)&(aliasFromRegion->idStr),(void *)aliasFromRegion,&status);

View File

@ -433,7 +433,12 @@ TimeZone::createTimeZone(const UnicodeString& ID)
} }
if (result == 0) { if (result == 0) {
U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)")); U_DEBUG_TZ_MSG(("failed to load time zone with id - falling to Etc/Unknown(GMT)"));
result = getUnknown().clone(); const TimeZone& unknown = getUnknown();
if (&unknown == NULL) { // Illegal NULL reference!
U_DEBUG_TZ_MSG(("failed to getUnknown()"));
} else {
result = unknown.clone();
}
} }
return result; return result;
} }

View File

@ -1007,6 +1007,12 @@ collectCurrencyNames(const char* locale,
*currencySymbols = (CurrencyNameStruct*)uprv_malloc *currencySymbols = (CurrencyNameStruct*)uprv_malloc
(sizeof(CurrencyNameStruct) * (*total_currency_symbol_count)); (sizeof(CurrencyNameStruct) * (*total_currency_symbol_count));
if(currencyNames == NULL || currencySymbols == NULL) {
ec = U_MEMORY_ALLOCATION_ERROR;
}
if (U_FAILURE(ec)) return;
const UChar* s = NULL; // currency name const UChar* s = NULL; // currency name
char* iso = NULL; // currency ISO code char* iso = NULL; // currency ISO code
@ -1174,6 +1180,15 @@ collectCurrencyNames(const char* locale,
printf("len: %d\n", (*currencySymbols)[index].currencyNameLen); printf("len: %d\n", (*currencySymbols)[index].currencyNameLen);
} }
#endif #endif
// fail on hashtable errors
if (U_FAILURE(ec3)) {
ec = ec3;
return;
}
if (U_FAILURE(ec4)) {
ec = ec4;
return;
}
} }
// @param currencyNames: currency names array // @param currencyNames: currency names array

View File

@ -483,7 +483,7 @@ private:
}; };
void initData(const Locale &locale, UErrorCode &status); void initData(const Locale &locale, UErrorCode &status);
void addCanonicalItems(); void addCanonicalItems(UErrorCode &status);
void addICUPatterns(const Locale& locale, UErrorCode& status); void addICUPatterns(const Locale& locale, UErrorCode& status);
void hackTimes(const UnicodeString& hackPattern, UErrorCode& status); void hackTimes(const UnicodeString& hackPattern, UErrorCode& status);
void addCLDRData(const Locale& locale, UErrorCode& status); void addCLDRData(const Locale& locale, UErrorCode& status);