ICU-699 add StringEnumeration default implementations

X-SVN-Rev: 13595
This commit is contained in:
Markus Scherer 2003-11-05 22:00:21 +00:00
parent 9de47b7b54
commit e7251a2b04
3 changed files with 160 additions and 29 deletions

View file

@ -1176,30 +1176,7 @@ public:
const UnicodeString* snext(UErrorCode& status) {
int32_t resultLength = 0;
const char* starter = next(&resultLength, status);
if(starter != NULL) {
UChar *buffer = currUSKey.getBuffer(resultLength+1);
if(buffer != NULL) {
u_charsToUChars(starter, buffer, resultLength);
buffer[resultLength] = 0;
currUSKey.releaseBuffer(resultLength);
return &currUSKey;
} else {
status = U_MEMORY_ALLOCATION_ERROR;
}
}
return NULL;
}
const UChar* unext(int32_t* resultLength, UErrorCode& status) {
if(snext(status) != NULL) {
if(resultLength != NULL) {
*resultLength = currUSKey.length();
}
return currUSKey.getTerminatedBuffer();
} else {
return NULL;
}
return setChars(next(&resultLength, status), resultLength, status);
}
void reset(UErrorCode& /*status*/) {

View file

@ -11,11 +11,10 @@
#define STRENUM_H
#include "unicode/uobject.h"
#include "unicode/unistr.h"
U_NAMESPACE_BEGIN
class UnicodeString;
/**
* Base class for 'pure' C++ implementations of uenum api. Adds a
* method that returns the next UnicodeString since in C++ this can
@ -43,6 +42,9 @@ class UnicodeString;
* upon any subsequent call to the enumeration's destructor, next,
* unext, snext, or reset.</p>
*
* ICU 2.8 adds some default implementations and helper functions
* for subclasses.
*
* @draft ICU 2.4
*/
class U_COMMON_API StringEnumeration : public UObject {
@ -109,13 +111,16 @@ public:
* status is set to U_INVARIANT_CONVERSION_ERROR and the return
* value is undefined (though not NULL).</p>
*
* Starting with ICU 2.8, the default implementation calls snext()
* and handles the conversion.
*
* @param status the error code.
* @param resultLength a pointer to receive the length, can be NULL.
* @return a pointer to the string, or NULL.
*
* @draft ICU 2.4
*/
virtual const char* next(int32_t *resultLength, UErrorCode& status) = 0;
virtual const char* next(int32_t *resultLength, UErrorCode& status);
/**
* <p>Returns the next element as a NUL-terminated UChar*. If there
@ -131,13 +136,16 @@ public:
* <p>If the iterator is out of sync with its service, status is set
* to U_ENUM_OUT_OF_SYNC_ERROR and NULL is returned.</p>
*
* Starting with ICU 2.8, the default implementation calls snext()
* and handles the conversion.
*
* @param status the error code.
* @param resultLength a ponter to receive the length, can be NULL.
* @return a pointer to the string, or NULL.
*
* @draft ICU 2.4
*/
virtual const UChar* unext(int32_t *resultLength, UErrorCode& status) = 0;
virtual const UChar* unext(int32_t *resultLength, UErrorCode& status);
/**
* <p>Returns the next element a UnicodeString*. If there are no
@ -170,6 +178,68 @@ public:
* @draft ICU 2.4
*/
virtual void reset(UErrorCode& status) = 0;
protected:
/**
* UnicodeString field for use with default implementations and subclasses.
* @draft ICU 2.8
*/
UnicodeString unistr;
/**
* char * default buffer for use with default implementations and subclasses.
* @draft ICU 2.8
*/
char charsBuffer[32];
/**
* char * buffer for use with default implementations and subclasses.
* Allocated in constructor and in ensureCharsCapacity().
* @draft ICU 2.8
*/
char *chars;
/**
* Capacity of chars, for use with default implementations and subclasses.
* @draft ICU 2.8
*/
int32_t charsCapacity;
/**
* Default constructor for use with default implementations and subclasses.
* @draft ICU 2.8
*/
StringEnumeration();
/**
* Ensures that chars is at least as large as the requested capacity.
* For use with default implementations and subclasses.
*
* @param capacity Requested capacity.
* @param status ICU in/out error code.
* @draft ICU 2.8
*/
void ensureCharsCapacity(int32_t capacity, UErrorCode &status);
/**
* Converts s to Unicode and sets unistr to the result.
* For use with default implementations and subclasses,
* especially for implementations of snext() in terms of next().
* This is provided with a helper function instead of a default implementation
* of snext() to avoid potential infinite loops between next() and snext().
*
* For example:
* \code
* const UnicodeString* snext(UErrorCode& status) {
* int32_t resultLength=0;
* return setChars(next(&resultLength, status), resultLength, status);
* }
* \endcode
*
* @param s String to be converted to Unicode.
* @param length Length of the string.
* @param status ICU in/out error code.
* @return A pointer to unistr.
* @draft ICU 2.8
*/
UnicodeString *setChars(const char *s, int32_t length, UErrorCode &status);
};
U_NAMESPACE_END

View file

@ -15,7 +15,11 @@
#include "cstring.h"
#include "cmemory.h"
#define THIS(en) ((StringEnumeration*)(en->context))
// StringEnumeration implementation ---------------------------------------- ***
StringEnumeration::StringEnumeration()
: chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
}
StringEnumeration::~StringEnumeration() {}
@ -25,6 +29,86 @@ StringEnumeration::clone() const {
return NULL;
}
const char *
StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
const UnicodeString *s=snext(status);
if(s!=NULL) {
unistr=*s;
ensureCharsCapacity(unistr.length()+1, status);
if(U_SUCCESS(status)) {
if(resultLength!=NULL) {
*resultLength=unistr.length();
}
unistr.extract(0, INT32_MAX, chars, charsCapacity, "");
return chars;
}
}
return NULL;
}
const UChar *
StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
const UnicodeString *s=snext(status);
if(s!=NULL) {
unistr=*s;
if(U_SUCCESS(status)) {
if(resultLength!=NULL) {
*resultLength=unistr.length();
}
return unistr.getTerminatedBuffer();
}
}
return NULL;
}
void
StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) {
if(U_SUCCESS(status) && capacity>charsCapacity) {
if(capacity<(charsCapacity+charsCapacity/2)) {
// avoid allocation thrashing
capacity=charsCapacity+charsCapacity/2;
}
if(chars!=charsBuffer) {
uprv_free(chars);
}
chars=(char *)uprv_malloc(capacity);
if(chars==NULL) {
chars=charsBuffer;
charsCapacity=sizeof(charsBuffer);
status=U_MEMORY_ALLOCATION_ERROR;
} else {
charsCapacity=capacity;
}
}
}
UnicodeString *
StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
if(U_SUCCESS(status) && s!=NULL) {
if(length<0) {
length=uprv_strlen(s);
}
UChar *buffer=unistr.getBuffer(length+1);
if(buffer!=NULL) {
u_charsToUChars(s, buffer, length);
buffer[length]=0;
unistr.releaseBuffer(length);
return &unistr;
} else {
status=U_MEMORY_ALLOCATION_ERROR;
}
}
return NULL;
}
// C wrapper --------------------------------------------------------------- ***
#define THIS(en) ((StringEnumeration*)(en->context))
U_CDECL_BEGIN
/**