1 // Copyright (C) 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 **********************************************************************
5 * Copyright (c) 2002-2014, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 **********************************************************************
9 * Created: November 11 2002
11 **********************************************************************
13 #include "utypeinfo.h" // for 'typeid' to work
15 #include "unicode/ustring.h"
16 #include "unicode/strenum.h"
17 #include "unicode/putil.h"
25 // StringEnumeration implementation ---------------------------------------- ***
27 StringEnumeration::StringEnumeration()
28 : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
31 StringEnumeration::~StringEnumeration() {
32 if (chars != NULL && chars != charsBuffer) {
37 // StringEnumeration base class clone() default implementation, does not clone
39 StringEnumeration::clone() const {
44 StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
45 const UnicodeString *s=snext(status);
46 if(U_SUCCESS(status) && s!=NULL) {
48 ensureCharsCapacity(unistr.length()+1, status);
49 if(U_SUCCESS(status)) {
50 if(resultLength!=NULL) {
51 *resultLength=unistr.length();
53 unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV);
62 StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
63 const UnicodeString *s=snext(status);
64 if(U_SUCCESS(status) && s!=NULL) {
66 if(resultLength!=NULL) {
67 *resultLength=unistr.length();
69 return unistr.getTerminatedBuffer();
76 StringEnumeration::snext(UErrorCode &status) {
78 const char *s=next(&length, status);
79 return setChars(s, length, status);
83 StringEnumeration::ensureCharsCapacity(int32_t capacity, UErrorCode &status) {
84 if(U_SUCCESS(status) && capacity>charsCapacity) {
85 if(capacity<(charsCapacity+charsCapacity/2)) {
86 // avoid allocation thrashing
87 capacity=charsCapacity+charsCapacity/2;
89 if(chars!=charsBuffer) {
92 chars=(char *)uprv_malloc(capacity);
95 charsCapacity=sizeof(charsBuffer);
96 status=U_MEMORY_ALLOCATION_ERROR;
98 charsCapacity=capacity;
104 StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
105 if(U_SUCCESS(status) && s!=NULL) {
107 length=(int32_t)uprv_strlen(s);
110 UChar *buffer=unistr.getBuffer(length+1);
112 u_charsToUChars(s, buffer, length);
114 unistr.releaseBuffer(length);
117 status=U_MEMORY_ALLOCATION_ERROR;
124 StringEnumeration::operator==(const StringEnumeration& that)const {
125 return typeid(*this) == typeid(that);
129 StringEnumeration::operator!=(const StringEnumeration& that)const {
130 return !operator==(that);
133 // UStringEnumeration implementation --------------------------------------- ***
135 UStringEnumeration * U_EXPORT2
136 UStringEnumeration::fromUEnumeration(
137 UEnumeration *uenumToAdopt, UErrorCode &status) {
138 if (U_FAILURE(status)) {
139 uenum_close(uenumToAdopt);
142 UStringEnumeration *result = new UStringEnumeration(uenumToAdopt);
143 if (result == NULL) {
144 status = U_MEMORY_ALLOCATION_ERROR;
145 uenum_close(uenumToAdopt);
151 UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
153 U_ASSERT(_uenum != 0);
156 UStringEnumeration::~UStringEnumeration() {
160 int32_t UStringEnumeration::count(UErrorCode& status) const {
161 return uenum_count(uenum, &status);
164 const char *UStringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
165 return uenum_next(uenum, resultLength, &status);
168 const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
170 const UChar* str = uenum_unext(uenum, &length, &status);
171 if (str == 0 || U_FAILURE(status)) {
174 return &unistr.setTo(str, length);
177 void UStringEnumeration::reset(UErrorCode& status) {
178 uenum_reset(uenum, &status);
181 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration)
184 // C wrapper --------------------------------------------------------------- ***
186 #define THIS(en) ((icu::StringEnumeration*)(en->context))
191 * Wrapper API to make StringEnumeration look like UEnumeration.
193 static void U_CALLCONV
194 ustrenum_close(UEnumeration* en) {
200 * Wrapper API to make StringEnumeration look like UEnumeration.
202 static int32_t U_CALLCONV
203 ustrenum_count(UEnumeration* en,
206 return THIS(en)->count(*ec);
210 * Wrapper API to make StringEnumeration look like UEnumeration.
212 static const UChar* U_CALLCONV
213 ustrenum_unext(UEnumeration* en,
214 int32_t* resultLength,
217 return THIS(en)->unext(resultLength, *ec);
221 * Wrapper API to make StringEnumeration look like UEnumeration.
223 static const char* U_CALLCONV
224 ustrenum_next(UEnumeration* en,
225 int32_t* resultLength,
228 return THIS(en)->next(resultLength, *ec);
232 * Wrapper API to make StringEnumeration look like UEnumeration.
234 static void U_CALLCONV
235 ustrenum_reset(UEnumeration* en,
238 THIS(en)->reset(*ec);
242 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
243 * The StringEnumeration pointer will be stored in 'context'.
245 static const UEnumeration USTRENUM_VT = {
247 NULL, // store StringEnumeration pointer here
258 * Given a StringEnumeration, wrap it in a UEnumeration. The
259 * StringEnumeration is adopted; after this call, the caller must not
260 * delete it (regardless of error status).
262 U_CAPI UEnumeration* U_EXPORT2
263 uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec) {
264 UEnumeration* result = NULL;
265 if (U_SUCCESS(*ec) && adopted != NULL) {
266 result = (UEnumeration*) uprv_malloc(sizeof(UEnumeration));
267 if (result == NULL) {
268 *ec = U_MEMORY_ALLOCATION_ERROR;
270 uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
271 result->context = adopted;
274 if (result == NULL) {
280 // C wrapper --------------------------------------------------------------- ***
284 typedef struct UCharStringEnumeration {
286 int32_t index, count;
287 } UCharStringEnumeration;
289 static void U_CALLCONV
290 ucharstrenum_close(UEnumeration* en) {
294 static int32_t U_CALLCONV
295 ucharstrenum_count(UEnumeration* en,
296 UErrorCode* /*ec*/) {
297 return ((UCharStringEnumeration*)en)->count;
300 static const UChar* U_CALLCONV
301 ucharstrenum_unext(UEnumeration* en,
302 int32_t* resultLength,
303 UErrorCode* /*ec*/) {
304 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
305 if (e->index >= e->count) {
308 const UChar* result = ((const UChar**)e->uenum.context)[e->index++];
310 *resultLength = (int32_t)u_strlen(result);
316 static const char* U_CALLCONV
317 ucharstrenum_next(UEnumeration* en,
318 int32_t* resultLength,
319 UErrorCode* /*ec*/) {
320 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
321 if (e->index >= e->count) {
324 const char* result = ((const char**)e->uenum.context)[e->index++];
326 *resultLength = (int32_t)uprv_strlen(result);
331 static void U_CALLCONV
332 ucharstrenum_reset(UEnumeration* en,
333 UErrorCode* /*ec*/) {
334 ((UCharStringEnumeration*)en)->index = 0;
337 static const UEnumeration UCHARSTRENUM_VT = {
339 NULL, // store StringEnumeration pointer here
347 static const UEnumeration UCHARSTRENUM_U_VT = {
349 NULL, // store StringEnumeration pointer here
359 U_CAPI UEnumeration* U_EXPORT2
360 uenum_openCharStringsEnumeration(const char* const strings[], int32_t count,
362 UCharStringEnumeration* result = NULL;
363 if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
364 result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
365 if (result == NULL) {
366 *ec = U_MEMORY_ALLOCATION_ERROR;
368 U_ASSERT((char*)result==(char*)(&result->uenum));
369 uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
370 result->uenum.context = (void*)strings;
372 result->count = count;
375 return (UEnumeration*) result;
378 U_CAPI UEnumeration* U_EXPORT2
379 uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count,
381 UCharStringEnumeration* result = NULL;
382 if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
383 result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
384 if (result == NULL) {
385 *ec = U_MEMORY_ALLOCATION_ERROR;
387 U_ASSERT((char*)result==(char*)(&result->uenum));
388 uprv_memcpy(result, &UCHARSTRENUM_U_VT, sizeof(UCHARSTRENUM_U_VT));
389 result->uenum.context = (void*)strings;
391 result->count = count;
394 return (UEnumeration*) result;