2 **********************************************************************
3 * Copyright (c) 2002-2014, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 * Created: November 11 2002
9 **********************************************************************
11 #include "utypeinfo.h" // for 'typeid' to work
13 #include "unicode/ustring.h"
14 #include "unicode/strenum.h"
15 #include "unicode/putil.h"
23 // StringEnumeration implementation ---------------------------------------- ***
25 StringEnumeration::StringEnumeration()
26 : chars(charsBuffer
), charsCapacity(sizeof(charsBuffer
)) {
29 StringEnumeration::~StringEnumeration() {
30 if (chars
!= NULL
&& chars
!= charsBuffer
) {
35 // StringEnumeration base class clone() default implementation, does not clone
37 StringEnumeration::clone() const {
42 StringEnumeration::next(int32_t *resultLength
, UErrorCode
&status
) {
43 const UnicodeString
*s
=snext(status
);
44 if(U_SUCCESS(status
) && s
!=NULL
) {
46 ensureCharsCapacity(unistr
.length()+1, status
);
47 if(U_SUCCESS(status
)) {
48 if(resultLength
!=NULL
) {
49 *resultLength
=unistr
.length();
51 unistr
.extract(0, INT32_MAX
, chars
, charsCapacity
, US_INV
);
60 StringEnumeration::unext(int32_t *resultLength
, UErrorCode
&status
) {
61 const UnicodeString
*s
=snext(status
);
62 if(U_SUCCESS(status
) && s
!=NULL
) {
64 if(resultLength
!=NULL
) {
65 *resultLength
=unistr
.length();
67 return unistr
.getTerminatedBuffer();
74 StringEnumeration::snext(UErrorCode
&status
) {
76 const char *s
=next(&length
, status
);
77 return setChars(s
, length
, status
);
81 StringEnumeration::ensureCharsCapacity(int32_t capacity
, UErrorCode
&status
) {
82 if(U_SUCCESS(status
) && capacity
>charsCapacity
) {
83 if(capacity
<(charsCapacity
+charsCapacity
/2)) {
84 // avoid allocation thrashing
85 capacity
=charsCapacity
+charsCapacity
/2;
87 if(chars
!=charsBuffer
) {
90 chars
=(char *)uprv_malloc(capacity
);
93 charsCapacity
=sizeof(charsBuffer
);
94 status
=U_MEMORY_ALLOCATION_ERROR
;
96 charsCapacity
=capacity
;
102 StringEnumeration::setChars(const char *s
, int32_t length
, UErrorCode
&status
) {
103 if(U_SUCCESS(status
) && s
!=NULL
) {
105 length
=(int32_t)uprv_strlen(s
);
108 UChar
*buffer
=unistr
.getBuffer(length
+1);
110 u_charsToUChars(s
, buffer
, length
);
112 unistr
.releaseBuffer(length
);
115 status
=U_MEMORY_ALLOCATION_ERROR
;
122 StringEnumeration::operator==(const StringEnumeration
& that
)const {
123 return typeid(*this) == typeid(that
);
127 StringEnumeration::operator!=(const StringEnumeration
& that
)const {
128 return !operator==(that
);
131 // UStringEnumeration implementation --------------------------------------- ***
133 UStringEnumeration
* U_EXPORT2
134 UStringEnumeration::fromUEnumeration(
135 UEnumeration
*uenumToAdopt
, UErrorCode
&status
) {
136 if (U_FAILURE(status
)) {
137 uenum_close(uenumToAdopt
);
140 UStringEnumeration
*result
= new UStringEnumeration(uenumToAdopt
);
141 if (result
== NULL
) {
142 status
= U_MEMORY_ALLOCATION_ERROR
;
143 uenum_close(uenumToAdopt
);
149 UStringEnumeration::UStringEnumeration(UEnumeration
* _uenum
) :
151 U_ASSERT(_uenum
!= 0);
154 UStringEnumeration::~UStringEnumeration() {
158 int32_t UStringEnumeration::count(UErrorCode
& status
) const {
159 return uenum_count(uenum
, &status
);
162 const char *UStringEnumeration::next(int32_t *resultLength
, UErrorCode
&status
) {
163 return uenum_next(uenum
, resultLength
, &status
);
166 const UnicodeString
* UStringEnumeration::snext(UErrorCode
& status
) {
168 const UChar
* str
= uenum_unext(uenum
, &length
, &status
);
169 if (str
== 0 || U_FAILURE(status
)) {
172 return &unistr
.setTo(str
, length
);
175 void UStringEnumeration::reset(UErrorCode
& status
) {
176 uenum_reset(uenum
, &status
);
179 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration
)
182 // C wrapper --------------------------------------------------------------- ***
184 #define THIS(en) ((icu::StringEnumeration*)(en->context))
189 * Wrapper API to make StringEnumeration look like UEnumeration.
191 static void U_CALLCONV
192 ustrenum_close(UEnumeration
* en
) {
198 * Wrapper API to make StringEnumeration look like UEnumeration.
200 static int32_t U_CALLCONV
201 ustrenum_count(UEnumeration
* en
,
204 return THIS(en
)->count(*ec
);
208 * Wrapper API to make StringEnumeration look like UEnumeration.
210 static const UChar
* U_CALLCONV
211 ustrenum_unext(UEnumeration
* en
,
212 int32_t* resultLength
,
215 return THIS(en
)->unext(resultLength
, *ec
);
219 * Wrapper API to make StringEnumeration look like UEnumeration.
221 static const char* U_CALLCONV
222 ustrenum_next(UEnumeration
* en
,
223 int32_t* resultLength
,
226 return THIS(en
)->next(resultLength
, *ec
);
230 * Wrapper API to make StringEnumeration look like UEnumeration.
232 static void U_CALLCONV
233 ustrenum_reset(UEnumeration
* en
,
236 THIS(en
)->reset(*ec
);
240 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
241 * The StringEnumeration pointer will be stored in 'context'.
243 static const UEnumeration USTRENUM_VT
= {
245 NULL
, // store StringEnumeration pointer here
256 * Given a StringEnumeration, wrap it in a UEnumeration. The
257 * StringEnumeration is adopted; after this call, the caller must not
258 * delete it (regardless of error status).
260 U_CAPI UEnumeration
* U_EXPORT2
261 uenum_openFromStringEnumeration(icu::StringEnumeration
* adopted
, UErrorCode
* ec
) {
262 UEnumeration
* result
= NULL
;
263 if (U_SUCCESS(*ec
) && adopted
!= NULL
) {
264 result
= (UEnumeration
*) uprv_malloc(sizeof(UEnumeration
));
265 if (result
== NULL
) {
266 *ec
= U_MEMORY_ALLOCATION_ERROR
;
268 uprv_memcpy(result
, &USTRENUM_VT
, sizeof(USTRENUM_VT
));
269 result
->context
= adopted
;
272 if (result
== NULL
) {
278 // C wrapper --------------------------------------------------------------- ***
282 typedef struct UCharStringEnumeration
{
284 int32_t index
, count
;
285 } UCharStringEnumeration
;
287 static void U_CALLCONV
288 ucharstrenum_close(UEnumeration
* en
) {
292 static int32_t U_CALLCONV
293 ucharstrenum_count(UEnumeration
* en
,
294 UErrorCode
* /*ec*/) {
295 return ((UCharStringEnumeration
*)en
)->count
;
298 static const UChar
* U_CALLCONV
299 ucharstrenum_unext(UEnumeration
* en
,
300 int32_t* resultLength
,
301 UErrorCode
* /*ec*/) {
302 UCharStringEnumeration
*e
= (UCharStringEnumeration
*) en
;
303 if (e
->index
>= e
->count
) {
306 const UChar
* result
= ((const UChar
**)e
->uenum
.context
)[e
->index
++];
308 *resultLength
= (int32_t)u_strlen(result
);
314 static const char* U_CALLCONV
315 ucharstrenum_next(UEnumeration
* en
,
316 int32_t* resultLength
,
317 UErrorCode
* /*ec*/) {
318 UCharStringEnumeration
*e
= (UCharStringEnumeration
*) en
;
319 if (e
->index
>= e
->count
) {
322 const char* result
= ((const char**)e
->uenum
.context
)[e
->index
++];
324 *resultLength
= (int32_t)uprv_strlen(result
);
329 static void U_CALLCONV
330 ucharstrenum_reset(UEnumeration
* en
,
331 UErrorCode
* /*ec*/) {
332 ((UCharStringEnumeration
*)en
)->index
= 0;
335 static const UEnumeration UCHARSTRENUM_VT
= {
337 NULL
, // store StringEnumeration pointer here
345 static const UEnumeration UCHARSTRENUM_U_VT
= {
347 NULL
, // store StringEnumeration pointer here
357 U_CAPI UEnumeration
* U_EXPORT2
358 uenum_openCharStringsEnumeration(const char* const strings
[], int32_t count
,
360 UCharStringEnumeration
* result
= NULL
;
361 if (U_SUCCESS(*ec
) && count
>= 0 && (count
== 0 || strings
!= 0)) {
362 result
= (UCharStringEnumeration
*) uprv_malloc(sizeof(UCharStringEnumeration
));
363 if (result
== NULL
) {
364 *ec
= U_MEMORY_ALLOCATION_ERROR
;
366 U_ASSERT((char*)result
==(char*)(&result
->uenum
));
367 uprv_memcpy(result
, &UCHARSTRENUM_VT
, sizeof(UCHARSTRENUM_VT
));
368 result
->uenum
.context
= (void*)strings
;
370 result
->count
= count
;
373 return (UEnumeration
*) result
;
376 U_CAPI UEnumeration
* U_EXPORT2
377 uenum_openUCharStringsEnumeration(const UChar
* const strings
[], int32_t count
,
379 UCharStringEnumeration
* result
= NULL
;
380 if (U_SUCCESS(*ec
) && count
>= 0 && (count
== 0 || strings
!= 0)) {
381 result
= (UCharStringEnumeration
*) uprv_malloc(sizeof(UCharStringEnumeration
));
382 if (result
== NULL
) {
383 *ec
= U_MEMORY_ALLOCATION_ERROR
;
385 U_ASSERT((char*)result
==(char*)(&result
->uenum
));
386 uprv_memcpy(result
, &UCHARSTRENUM_U_VT
, sizeof(UCHARSTRENUM_U_VT
));
387 result
->uenum
.context
= (void*)strings
;
389 result
->count
= count
;
392 return (UEnumeration
*) result
;