1 // © 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
;