diff --git a/icu4c/source/common/filestrm.c b/icu4c/source/common/filestrm.c index e74edab2250..206781d5863 100644 --- a/icu4c/source/common/filestrm.c +++ b/icu4c/source/common/filestrm.c @@ -33,8 +33,12 @@ U_CAPI FileStream* T_FileStream_open(const char* filename, const char* mode) { - FILE *file = fopen(filename, mode); - return (FileStream*)file; + if(filename != NULL && *filename != 0 && mode != NULL && *mode != 0) { + FILE *file = fopen(filename, mode); + return (FileStream*)file; + } else { + return NULL; + } } diff --git a/icu4c/source/common/normlzr.cpp b/icu4c/source/common/normlzr.cpp index 8acaec06798..0404302ba62 100644 --- a/icu4c/source/common/normlzr.cpp +++ b/icu4c/source/common/normlzr.cpp @@ -109,7 +109,11 @@ Normalizer::~Normalizer() Normalizer* Normalizer::clone() const { - return new Normalizer(*this); + if(this!=0) { + return new Normalizer(*this); + } else { + return 0; + } } /** diff --git a/icu4c/source/common/uhash.c b/icu4c/source/common/uhash.c index 9e1be5b2521..34987ad1e04 100644 --- a/icu4c/source/common/uhash.c +++ b/icu4c/source/common/uhash.c @@ -21,6 +21,7 @@ #include "uhash.h" #include "ustring.h" +#include "cstring.h" #include "cmemory.h" /* Private function prototypes */ @@ -505,59 +506,69 @@ uhash_find(const UHashtable *hash, U_CAPI int32_t uhash_hashUString(const void *parm) { - const UChar *key = (const UChar*) parm; - int32_t len = u_strlen(key); - int32_t hash = UHASH_INVALID; - const UChar *limit = key + len; - int32_t inc = (len >= 128 ? len/64 : 1); + if(parm != NULL) { + const UChar *key = (const UChar*) parm; + int32_t len = u_strlen(key); + int32_t hash = UHASH_INVALID; + const UChar *limit = key + len; + int32_t inc = (len >= 128 ? len/64 : 1); - /* - We compute the hash by iterating sparsely over 64 (at most) characters - spaced evenly through the string. For each character, we multiply the - previous hash value by a prime number and add the new character in, - in the manner of a additive linear congruential random number generator, - thus producing a pseudorandom deterministic value which should be well - distributed over the output range. [LIU] - */ + /* + We compute the hash by iterating sparsely over 64 (at most) characters + spaced evenly through the string. For each character, we multiply the + previous hash value by a prime number and add the new character in, + in the manner of a additive linear congruential random number generator, + thus producing a pseudorandom deterministic value which should be well + distributed over the output range. [LIU] + */ - while(key < limit) { - hash = (hash * 37) + *key; - key += inc; + while(key < limit) { + hash = (hash * 37) + *key; + key += inc; + } + + if(hash == UHASH_INVALID) { + hash = UHASH_EMPTY; + } + + return hash & 0x7FFFFFFF; + } else { + return UHASH_INVALID; } - - if(hash == UHASH_INVALID) - hash = UHASH_EMPTY; - - return hash & 0x7FFFFFFF; } U_CAPI int32_t uhash_hashString(const void *parm) { - const char *key = (const char*) parm; - int32_t len = strlen(key); - int32_t hash = UHASH_INVALID; - const char *limit = key + len; - int32_t inc = (len >= 128 ? len/64 : 1); + if(parm != NULL) { + const char *key = (const char*) parm; + int32_t len = icu_strlen(key); + int32_t hash = UHASH_INVALID; + const char *limit = key + len; + int32_t inc = (len >= 128 ? len/64 : 1); - /* - We compute the hash by iterating sparsely over 64 (at most) characters - spaced evenly through the string. For each character, we multiply the - previous hash value by a prime number and add the new character in, - in the manner of a additive linear congruential random number generator, - thus producing a pseudorandom deterministic value which should be well - distributed over the output range. [LIU] - */ + /* + We compute the hash by iterating sparsely over 64 (at most) characters + spaced evenly through the string. For each character, we multiply the + previous hash value by a prime number and add the new character in, + in the manner of a additive linear congruential random number generator, + thus producing a pseudorandom deterministic value which should be well + distributed over the output range. [LIU] + */ - while(key < limit) { - hash = (hash * 37) + *key; - key += inc; + while(key < limit) { + hash = (hash * 37) + *key; + key += inc; + } + + if(hash == UHASH_INVALID) { + hash = UHASH_EMPTY; + } + + return hash & 0x7FFFFFFF; + } else { + return UHASH_INVALID; } - - if(hash == UHASH_INVALID) - hash = UHASH_EMPTY; - - return hash & 0x7FFFFFFF; } U_CAPI int32_t diff --git a/icu4c/source/common/unistr.cpp b/icu4c/source/common/unistr.cpp index f438de37287..669dd83209b 100644 --- a/icu4c/source/common/unistr.cpp +++ b/icu4c/source/common/unistr.cpp @@ -492,6 +492,10 @@ UnicodeString::doLastIndexOf(UChar c, UTextOffset start, int32_t length) const { + if(isBogus()) { + return -1; + } + // pin indices pinIndices(start, length); if(length == 0) { diff --git a/icu4c/source/common/unistr.h b/icu4c/source/common/unistr.h index bc6787d53e7..1b96d17eab8 100644 --- a/icu4c/source/common/unistr.h +++ b/icu4c/source/common/unistr.h @@ -1615,8 +1615,16 @@ UnicodeString::UnicodeString(const UnicodeString& that) //======================================== inline bool_t UnicodeString::operator== (const UnicodeString& text) const -{ return (fLength == text.fLength - && doCompare(0, fLength, text, 0, text.fLength) == 0); } +{ + if(isBogus()) { + return text.isBogus(); + } else { + return + !text.isBogus() && + fLength == text.fLength && + doCompare(0, fLength, text, 0, text.fLength) == 0; + } +} inline bool_t UnicodeString::operator!= (const UnicodeString& text) const diff --git a/icu4c/source/common/ustring.c b/icu4c/source/common/ustring.c index 66c69f0a48f..0238fa57ffb 100644 --- a/icu4c/source/common/ustring.c +++ b/icu4c/source/common/ustring.c @@ -36,11 +36,16 @@ UChar* u_strcat(UChar *dst, const UChar *src) { - UChar *anchor = dst; /* save a pointer to start of dst */ - - while(*dst++); /* To end of first string */ - dst--; /* Return to the null */ - while(*dst++ = *src++); /* copy string 2 over */ + UChar *anchor = dst; /* save a pointer to start of dst */ + + while(*dst != 0) { /* To end of first string */ + ++dst; + } + while((*dst = *src) != 0) { /* copy string 2 over */ + ++dst; + ++src; + } + return anchor; } @@ -49,26 +54,37 @@ u_strncat(UChar *dst, const UChar *src, int32_t n ) { - UChar *anchor = dst; /* save a pointer to start of dst */ + if(n > 0) { + UChar *anchor = dst; /* save a pointer to start of dst */ + + while(*dst != 0) { /* To end of first string */ + ++dst; + } + while((*dst = *src) != 0) { /* copy string 2 over */ + ++dst; + if(--n == 0) { + *dst = 0; + break; + } + ++src; + } - if (!n) return dst; - while(*dst++); /* To end of first string */ - dst--; /* Return to the null */ - while((*dst++ = *src++) && --n); /* copy string 2 over */ - *dst = 0x0000; - - return anchor; + return anchor; + } else { + return dst; + } } UChar* u_strchr(const UChar *s, UChar c) { - while((*s != c) && *s) - s++; - - if(*s == c) - return (UChar*) s; + while(*s != 0) { + if(*s == c) { + return (UChar *)s; + } + ++s; + } return NULL; } @@ -76,12 +92,15 @@ int32_t u_strcmp(const UChar *s1, const UChar *s2) { - while((*s1 == *s2) && *s1) { - s1++; - s2++; + int32_t rc; + for(;;) { + rc = (int32_t)*s1 - (int32_t)*s2; + if(rc != 0 || *s1 == 0) { + return rc; + } + ++s1; + ++s2; } - - return (int32_t)*s1 - (int32_t)*s2; } int32_t @@ -89,21 +108,32 @@ u_strncmp(const UChar *s1, const UChar *s2, int32_t n) { - if (!n) return 0; - while((*s1 == *s2) && *s1 && --n) { - s1++; - s2++; + if(n > 0) { + int32_t rc; + for(;;) { + rc = (int32_t)*s1 - (int32_t)*s2; + if(rc != 0 || *s1 == 0 || --n == 0) { + return rc; + } + ++s1; + ++s2; + } + } else { + return 0; } - return (int32_t)*s1 - (int32_t)*s2; } UChar* u_strcpy(UChar *dst, const UChar *src) { - UChar *anchor = dst; /* save the start of result string */ - - while(*dst++ = *src++); + UChar *anchor = dst; /* save a pointer to start of dst */ + + while((*dst = *src) != 0) { /* copy string 2 over */ + ++dst; + ++src; + } + return anchor; } @@ -112,22 +142,36 @@ u_strncpy(UChar *dst, const UChar *src, int32_t n) { - UChar *anchor = dst; /* save the start of result string */ - - if (!n) return dst; - while((*dst++ = *src++) && --n); - *dst = 0x0000; + UChar *anchor = dst; /* save a pointer to start of dst */ + + if(n > 0) { + while((*dst = *src) != 0) { /* copy string 2 over */ + ++dst; + if(--n == 0) { + *dst = 0; + break; + } + ++src; + } + } else { + *dst = 0; + } + return anchor; } int32_t u_strlen(const UChar *s) { - int32_t i = 0; - - while(*s++) - i++; - return i; + if(U_SIZEOF_WCHAR_T == sizeof(UChar)) { + return icu_wcslen(s); + } else { + const UChar *t = s; + while(*t != 0) { + ++t; + } + return t - s; + } } @@ -136,12 +180,14 @@ UChar* u_uastrcpy(UChar *ucs1, { UErrorCode err = U_ZERO_ERROR; ucnv_toUChars(defaultConverter, - ucs1, - MAX_STRLEN, - s2, - icu_strlen(s2), - &err); - + ucs1, + MAX_STRLEN, + s2, + icu_strlen(s2), + &err); + if(U_FAILURE(err)) { + *ucs1 = 0; + } return ucs1; } @@ -150,33 +196,29 @@ UChar* u_uastrncpy(UChar *ucs1, int32_t n) { UErrorCode err = U_ZERO_ERROR; - int32_t end = ucnv_toUChars(defaultConverter, + ucnv_toUChars(defaultConverter, ucs1, n, s2, icu_strlen(s2), &err); - - ucs1[icu_min(end,n)] = 0x0000; + + if(U_FAILURE(err)) { + *ucs1 = 0; + } return ucs1; } char* u_austrcpy(char *s1, const UChar *ucs2 ) { - char * anchor = s1; /* save the start of result string */ UErrorCode err = U_ZERO_ERROR; int32_t len = ucnv_fromUChars(defaultConverter, s1, MAX_STRLEN, ucs2, &err); - - s1[len] = '\0'; + + s1[len] = 0; return s1; - } - - - - diff --git a/icu4c/source/i18n/smpdtfmt.cpp b/icu4c/source/i18n/smpdtfmt.cpp index 60471e941ae..2faeb2e7751 100644 --- a/icu4c/source/i18n/smpdtfmt.cpp +++ b/icu4c/source/i18n/smpdtfmt.cpp @@ -385,6 +385,10 @@ void SimpleDateFormat::parseAmbiguousDatesAsAfter(UDate startDate, UErrorCode& s UnicodeString& SimpleDateFormat::format(UDate date, UnicodeString& toAppendTo, FieldPosition& pos) const { + if (fCalendar == 0) { + return toAppendTo; + } + UErrorCode status = U_ZERO_ERROR; pos.setBeginIndex(0); pos.setEndIndex(0); diff --git a/icu4c/source/test/cintltst/cintltst.c b/icu4c/source/test/cintltst/cintltst.c index 44c30edf55d..93144380965 100644 --- a/icu4c/source/test/cintltst/cintltst.c +++ b/icu4c/source/test/cintltst/cintltst.c @@ -26,20 +26,32 @@ #include #include "uchar.h" #include "ustring.h" +#include "ucnv.h" static char* _testDirectory=NULL; int main ( int argc, char **argv ) { - - - TestNode *root = NULL; - addAllTests(&root); - processArgs(root, argc, argv); - + TestNode *root; - return 0; + /* initial check for the default converter */ + UErrorCode errorCode = U_ZERO_ERROR; + UConverter *cnv = ucnv_open(NULL, &errorCode); + if(cnv != NULL) { + // ok + ucnv_close(cnv); + } else { + fprintf(stderr, + "*** Failure! The default converter cannot be opened.\n" + "*** Check the ICU_DATA environment variable and \n" + "*** check that the data files are present.\n"); + return 1; + } - + root = NULL; + addAllTests(&root); + processArgs(root, argc, argv); + + return 0; } void diff --git a/icu4c/source/test/intltest/intltest.cpp b/icu4c/source/test/intltest/intltest.cpp index 3f9e299e981..7d21f4f9f72 100644 --- a/icu4c/source/test/intltest/intltest.cpp +++ b/icu4c/source/test/intltest/intltest.cpp @@ -654,7 +654,7 @@ bool_t IntlTest::runTestLoop( char* testname, char* par ) /** * Adds given string to the log if we are in verbose mode. */ -void IntlTest::log( UnicodeString message ) +void IntlTest::log( const UnicodeString &message ) { if( verbose ) { LL_message( message, FALSE ); @@ -665,7 +665,7 @@ void IntlTest::log( UnicodeString message ) * Adds given string to the log if we are in verbose mode. Adds a new line to * the given message. */ -void IntlTest::logln( UnicodeString message ) +void IntlTest::logln( const UnicodeString &message ) { if( verbose ) { LL_message( message, TRUE ); @@ -690,13 +690,13 @@ void IntlTest::err() { IncErrorCount(); } -void IntlTest::err( UnicodeString message ) +void IntlTest::err( const UnicodeString &message ) { IncErrorCount(); if (!no_err_msg) LL_message( message, FALSE ); } -void IntlTest::errln( UnicodeString message ) +void IntlTest::errln( const UnicodeString &message ) { IncErrorCount(); if (!no_err_msg) LL_message( message, TRUE ); @@ -862,6 +862,19 @@ main(int argc, char* argv[]) cout << " Leaks (l) : " << (leaks? "On" : "Off") << endl; cout << "-----------------------------------------------" << endl << endl; + // initial check for the default converter + UErrorCode errorCode = U_ZERO_ERROR; + UConverter *cnv = ucnv_open(0, &errorCode); + if(cnv != 0) { + // ok + ucnv_close(cnv); + } else { + cout << "*** Failure! The default converter cannot be opened." << endl << + "*** Check the ICU_DATA environment variable and " << endl << + "*** check that the data files are present." << endl; + return 1; + } + if (all) { major.runTest(); if (leaks) { diff --git a/icu4c/source/test/intltest/intltest.h b/icu4c/source/test/intltest/intltest.h index 00ea6fcb89b..5c5e5840064 100644 --- a/icu4c/source/test/intltest/intltest.h +++ b/icu4c/source/test/intltest/intltest.h @@ -68,17 +68,29 @@ public: virtual void setCaller( IntlTest* callingTest ); // for internal use only virtual void setPath( char* path ); // for internal use only - virtual void log( UnicodeString message ); + virtual void log( const UnicodeString &message ); + + // convenience function; assume that the message contains only invariant charcters + virtual void log( const char *message ); - virtual void logln( UnicodeString message ); + virtual void logln( const UnicodeString &message ); + + // convenience function; assume that the message contains only invariant charcters + virtual void logln( const char *message ); virtual void logln( void ); virtual void err(void); - virtual void err( UnicodeString message ); + virtual void err( const UnicodeString &message ); - virtual void errln( UnicodeString message ); + // convenience function; assume that the message contains only invariant charcters + virtual void err( const char *message ); + + virtual void errln( const UnicodeString &message ); + + // convenience function; assume that the message contains only invariant charcters + virtual void errln( const char *message ); virtual void usage( void ) ; @@ -136,6 +148,21 @@ public: }; +inline void IntlTest::log( const char *message ) { + log(UnicodeString(message, "")); +} + +inline void IntlTest::logln( const char *message ) { + logln(UnicodeString(message, "")); +} + +inline void IntlTest::err( const char *message ) { + err(UnicodeString(message, "")); +} + +inline void IntlTest::errln( const char *message ) { + errln(UnicodeString(message, "")); +} void it_log( UnicodeString message ); void it_logln( UnicodeString message ); diff --git a/icu4c/source/test/intltest/mnkytst.cpp b/icu4c/source/test/intltest/mnkytst.cpp index a04c2989b92..7eac59ee228 100644 --- a/icu4c/source/test/intltest/mnkytst.cpp +++ b/icu4c/source/test/intltest/mnkytst.cpp @@ -89,11 +89,16 @@ CollationMonkeyTest::checkValue(int32_t value) void CollationMonkeyTest::TestCollationKey( char* par ) { + if(source.length() == 0) { + errln(UNICODE_STRING("CollationMonkeyTest::TestCollationKey(): source is empty - ICU_DATA not set or data missing?", 92)); + return; + } + srand( (unsigned)time( NULL ) ); - int32_t s = checkValue(rand() % source.size()); - int32_t t = checkValue(rand() % source.size()); - int32_t slen = checkValue((rand() - source.size()) % source.size()); - int32_t tlen = checkValue((rand() - source.size()) % source.size()); + int32_t s = checkValue(rand() % source.length()); + int32_t t = checkValue(rand() % source.length()); + int32_t slen = checkValue((rand() - source.length()) % source.length()); + int32_t tlen = checkValue((rand() - source.length()) % source.length()); UnicodeString subs, subt; source.extract(MIN(s, slen), MAX(s, slen), subs); @@ -156,15 +161,19 @@ void CollationMonkeyTest::TestCollationKey( char* par ) void CollationMonkeyTest::TestCompare(char* par) { + if(source.length() == 0) { + errln(UNICODE_STRING("CollationMonkeyTest::TestCompare(): source is empty - ICU_DATA not set or data missing?", 87)); + return; + } /* Seed the random-number generator with current time so that * the numbers will be different every time we run. */ srand( (unsigned)time( NULL ) ); - int32_t s = checkValue(rand() % source.size()); - int32_t t = checkValue(rand() % source.size()); - int32_t slen = checkValue((rand() - source.size()) % source.size()); - int32_t tlen = checkValue((rand() - source.size()) % source.size()); + int32_t s = checkValue(rand() % source.length()); + int32_t t = checkValue(rand() % source.length()); + int32_t slen = checkValue((rand() - source.length()) % source.length()); + int32_t tlen = checkValue((rand() - source.length()) % source.length()); UnicodeString subs, subt; source.extract(MIN(s, slen), MAX(s, slen), subs);