ICU-699 add StringEnumeration default implementations

X-SVN-Rev: 13612
This commit is contained in:
Markus Scherer 2003-11-06 23:25:00 +00:00
parent 8830b45fa5
commit cc21ef7ba4
7 changed files with 123 additions and 55 deletions

View File

@ -691,9 +691,6 @@ private:
int32_t _timestamp;
UVector _ids;
int32_t _pos;
char *_bufp;
int32_t _buflen;
char _buf[32];
private:
ServiceEnumeration(const ICULocaleService* service, UErrorCode &status)
@ -701,8 +698,6 @@ private:
, _timestamp(service->getTimestamp())
, _ids(uhash_deleteUnicodeString, NULL, status)
, _pos(0)
, _bufp(_buf)
, _buflen(sizeof(_buf))
{
_service->getVisibleIDs(_ids, status);
}
@ -712,8 +707,6 @@ private:
, _timestamp(other._timestamp)
, _ids(uhash_deleteUnicodeString, NULL, status)
, _pos(0)
, _bufp(_buf)
, _buflen(sizeof(_buf))
{
if(U_SUCCESS(status)) {
int32_t i, length;
@ -740,11 +733,7 @@ public:
return NULL;
}
virtual ~ServiceEnumeration() {
if(_bufp != _buf) {
uprv_free(_bufp);
}
}
virtual ~ServiceEnumeration() {}
virtual StringEnumeration *clone() const {
UErrorCode status = U_ZERO_ERROR;
@ -760,32 +749,6 @@ public:
return upToDate(status) ? _ids.size() : 0;
}
const char* next(int32_t* resultLength, UErrorCode& status) {
const UnicodeString* us = snext(status);
if (us) {
int32_t newlen = us->length();
if (newlen >= _buflen) {
resizeBuffer(newlen + 1);
}
us->extract(0, INT32_MAX, _bufp, _buflen, "");
if (resultLength) {
*resultLength = newlen;
}
return _bufp;
}
return NULL;
}
const UChar* unext(int32_t* resultLength, UErrorCode& status) {
const UnicodeString* us = snext(status);
if (U_SUCCESS(status)) {
// the cast to a writable UnicodeString is safe because
// ICUService::getVisibleIDs() clones each string
return ((UnicodeString *)us)->getTerminatedBuffer();
}
return NULL;
}
const UnicodeString* snext(UErrorCode& status) {
if (upToDate(status) && (_pos < _ids.size())) {
return (const UnicodeString*)_ids[_pos++];
@ -793,15 +756,6 @@ public:
return NULL;
}
void resizeBuffer(int32_t newlen) {
if (_bufp != _buf) {
_bufp = (char *)uprv_realloc(_bufp, newlen);
} else {
_bufp = (char *)uprv_malloc(newlen);
}
_buflen = newlen;
}
UBool upToDate(UErrorCode& status) const {
if (U_SUCCESS(status)) {
if (_timestamp == _service->getTimestamp()) {

View File

@ -471,7 +471,7 @@ Locale& Locale::init(const char* localeID)
// "canonicalize" the locale ID to ICU/Java format
err = U_ZERO_ERROR;
length = uloc_getName(localeID, fullName, sizeof(fullNameBuffer), &err);
if(U_FAILURE(err) || err == U_STRING_NOT_TERMINATED_WARNING) {
if(err == U_BUFFER_OVERFLOW_ERROR || length >= sizeof(fullNameBuffer)) {
/*Go to heap for the fullName if necessary*/
fullName = (char *)uprv_malloc(sizeof(char)*(length + 1));
if(fullName == 0) {
@ -1176,7 +1176,8 @@ public:
const UnicodeString* snext(UErrorCode& status) {
int32_t resultLength = 0;
return setChars(next(&resultLength, status), resultLength, status);
const char *s = next(&resultLength, status);
return setChars(s, resultLength, status);
}
void reset(UErrorCode& /*status*/) {

View File

@ -229,7 +229,8 @@ protected:
* \code
* const UnicodeString* snext(UErrorCode& status) {
* int32_t resultLength=0;
* return setChars(next(&resultLength, status), resultLength, status);
* const char *s=next(&resultLength, status);
* return setChars(s, resultLength, status);
* }
* \endcode
*

View File

@ -1510,6 +1510,7 @@ LocaleTest::TestKeywordVariants(void) {
StringEnumeration *keywords;
int32_t keyCount = 0;
const char *keyword = NULL;
const UnicodeString *keywordString;
int32_t keywordLen = 0;
for(i = 0; i < sizeof(testCases)/sizeof(testCases[0]); i++) {
@ -1527,10 +1528,21 @@ LocaleTest::TestKeywordVariants(void) {
err("Expected to get %i keywords, got %i\n", testCases[i].numKeywords, keyCount);
}
if(keyCount) {
j = 0;
while(keyword = keywords->next(&keywordLen, status)) {
if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
for(j = 0;;) {
if((j&1)==0) {
if((keyword = keywords->next(&keywordLen, status)) == NULL) {
break;
}
if(strcmp(keyword, testCases[i].expectedKeywords[j]) != 0) {
err("Expected to get keyword value %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
}
} else {
if((keywordString = keywords->snext(status)) == NULL) {
break;
}
if(*keywordString != UnicodeString(testCases[i].expectedKeywords[j], "")) {
err("Expected to get keyword UnicodeString %s, got %s\n", testCases[i].expectedKeywords[j], keyword);
}
}
j++;

View File

@ -380,7 +380,11 @@ TimeZoneTest::TestGetAvailableIDs913()
s_length = s->count(ec);
for (i = 0; i < s_length;++i) {
if (i > 0) *buf += ", ";
*buf += *s->snext(ec);
if ((i & 1) == 0) {
*buf += *s->snext(ec);
} else {
*buf += UnicodeString(s->next(NULL, ec), "");
}
if((i % 5) == 4) {
// replace s with a clone of itself

View File

@ -54,6 +54,7 @@ void UnicodeStringTest::runIndexedTest( int32_t index, UBool exec, const char* &
case 12: name = "TestStackAllocation"; if (exec) TestStackAllocation(); break;
case 13: name = "TestUnescape"; if (exec) TestUnescape(); break;
case 14: name = "TestCountChar32"; if (exec) TestCountChar32(); break;
case 15: name = "TestStringEnumeration"; if (exec) TestStringEnumeration(); break;
default: name = ""; break; //needed to end loop
}
@ -1521,3 +1522,97 @@ UnicodeStringTest::TestBogus() {
errln("bogus<empty failed");
}
}
// StringEnumeration ------------------------------------------------------- ***
// most of StringEnumeration is tested elsewhere
// this test improves code coverage
static const char *const
testEnumStrings[]={
"a",
"b",
"c",
"this is a long string which helps us test some buffer limits",
"eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee"
};
class TestEnumeration : public StringEnumeration {
public:
TestEnumeration() : i(0) {}
virtual int32_t count(UErrorCode& status) const {
return LENGTHOF(testEnumStrings);
}
virtual const UnicodeString *snext(UErrorCode &status) {
if(U_SUCCESS(status) && i<LENGTHOF(testEnumStrings)) {
unistr=UnicodeString(testEnumStrings[i++], "");
return &unistr;
}
return NULL;
}
virtual void reset(UErrorCode &status) {
i=0;
}
static inline UClassID getStaticClassID() {
return (UClassID)&fgClassID;
}
virtual UClassID getDynamicClassID() const {
return getStaticClassID();
}
private:
static const char fgClassID;
int32_t i, length;
};
const char TestEnumeration::fgClassID=0;
void
UnicodeStringTest::TestStringEnumeration() {
UnicodeString s;
TestEnumeration ten;
int32_t i, length;
UErrorCode status;
const UChar *pu;
const char *pc;
// test the next() default implementation and ensureCharsCapacity()
for(i=0; i<LENGTHOF(testEnumStrings); ++i) {
status=U_ZERO_ERROR;
pc=ten.next(&length, status);
s=UnicodeString(testEnumStrings[i], "");
if(U_FAILURE(status) || pc==NULL || length!=s.length() || UnicodeString(pc, length, "")!=s) {
errln("StringEnumeration.next(%d) failed", i);
}
}
status=U_ZERO_ERROR;
if(ten.next(&length, status)!=NULL) {
errln("StringEnumeration.next(done)!=NULL");
}
// test the unext() default implementation
ten.reset(status);
for(i=0; i<LENGTHOF(testEnumStrings); ++i) {
status=U_ZERO_ERROR;
pu=ten.unext(&length, status);
s=UnicodeString(testEnumStrings[i], "");
if(U_FAILURE(status) || pu==NULL || length!=s.length() || UnicodeString(TRUE, pu, length)!=s) {
errln("StringEnumeration.unext(%d) failed", i);
}
}
status=U_ZERO_ERROR;
if(ten.unext(&length, status)!=NULL) {
errln("StringEnumeration.unext(done)!=NULL");
}
// test that the default clone() implementation works, and returns NULL
if(ten.clone()!=NULL) {
errln("StringEnumeration.clone()!=NULL");
}
}

View File

@ -71,6 +71,7 @@ public:
void _testUnicodeStringHasMoreChar32Than(const UnicodeString &s, int32_t start, int32_t length, int32_t number);
void TestCountChar32(void);
void TestBogus();
void TestStringEnumeration();
};
class StringCaseTest: public IntlTest {