2 **********************************************************************
3 * Copyright (c) 2002-2005, International Business Machines
4 * Corporation and others. All Rights Reserved.
5 **********************************************************************
7 * Created: November 11 2002
9 **********************************************************************
11 #include "unicode/ustring.h"
12 #include "unicode/strenum.h"
13 #include "unicode/putil.h"
21 // StringEnumeration implementation ---------------------------------------- ***
23 StringEnumeration::StringEnumeration()
24 : chars(charsBuffer
), charsCapacity(sizeof(charsBuffer
)) {
27 StringEnumeration::~StringEnumeration() {
28 if (chars
!= NULL
&& chars
!= charsBuffer
) {
33 // StringEnumeration base class clone() default implementation, does not clone
35 StringEnumeration::clone() const {
40 StringEnumeration::next(int32_t *resultLength
, UErrorCode
&status
) {
41 const UnicodeString
*s
=snext(status
);
44 ensureCharsCapacity(unistr
.length()+1, status
);
45 if(U_SUCCESS(status
)) {
46 if(resultLength
!=NULL
) {
47 *resultLength
=unistr
.length();
49 unistr
.extract(0, INT32_MAX
, chars
, charsCapacity
, US_INV
);
58 StringEnumeration::unext(int32_t *resultLength
, UErrorCode
&status
) {
59 const UnicodeString
*s
=snext(status
);
62 if(U_SUCCESS(status
)) {
63 if(resultLength
!=NULL
) {
64 *resultLength
=unistr
.length();
66 return unistr
.getTerminatedBuffer();
74 StringEnumeration::ensureCharsCapacity(int32_t capacity
, UErrorCode
&status
) {
75 if(U_SUCCESS(status
) && capacity
>charsCapacity
) {
76 if(capacity
<(charsCapacity
+charsCapacity
/2)) {
77 // avoid allocation thrashing
78 capacity
=charsCapacity
+charsCapacity
/2;
80 if(chars
!=charsBuffer
) {
83 chars
=(char *)uprv_malloc(capacity
);
86 charsCapacity
=sizeof(charsBuffer
);
87 status
=U_MEMORY_ALLOCATION_ERROR
;
89 charsCapacity
=capacity
;
95 StringEnumeration::setChars(const char *s
, int32_t length
, UErrorCode
&status
) {
96 if(U_SUCCESS(status
) && s
!=NULL
) {
98 length
=(int32_t)uprv_strlen(s
);
101 UChar
*buffer
=unistr
.getBuffer(length
+1);
103 u_charsToUChars(s
, buffer
, length
);
105 unistr
.releaseBuffer(length
);
108 status
=U_MEMORY_ALLOCATION_ERROR
;
115 StringEnumeration::operator==(const StringEnumeration
& that
)const {
116 return getDynamicClassID() == that
.getDynamicClassID();
120 StringEnumeration::operator!=(const StringEnumeration
& that
)const {
121 return !operator==(that
);
124 // UStringEnumeration implementation --------------------------------------- ***
126 UStringEnumeration::UStringEnumeration(UEnumeration
* _uenum
) :
128 U_ASSERT(_uenum
!= 0);
131 UStringEnumeration::~UStringEnumeration() {
135 int32_t UStringEnumeration::count(UErrorCode
& status
) const {
136 return uenum_count(uenum
, &status
);
139 const UnicodeString
* UStringEnumeration::snext(UErrorCode
& status
) {
141 const UChar
* str
= uenum_unext(uenum
, &length
, &status
);
142 if (str
== 0 || U_FAILURE(status
)) {
145 return &unistr
.setTo(str
, length
);
148 void UStringEnumeration::reset(UErrorCode
& status
) {
149 uenum_reset(uenum
, &status
);
152 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration
/*, StringEnumeration*/)
155 // C wrapper --------------------------------------------------------------- ***
157 #define THIS(en) ((StringEnumeration*)(en->context))
162 * Wrapper API to make StringEnumeration look like UEnumeration.
164 static void U_CALLCONV
165 ustrenum_close(UEnumeration
* en
) {
171 * Wrapper API to make StringEnumeration look like UEnumeration.
173 static int32_t U_CALLCONV
174 ustrenum_count(UEnumeration
* en
,
177 return THIS(en
)->count(*ec
);
181 * Wrapper API to make StringEnumeration look like UEnumeration.
183 static const UChar
* U_CALLCONV
184 ustrenum_unext(UEnumeration
* en
,
185 int32_t* resultLength
,
188 return THIS(en
)->unext(resultLength
, *ec
);
192 * Wrapper API to make StringEnumeration look like UEnumeration.
194 static const char* U_CALLCONV
195 ustrenum_next(UEnumeration
* en
,
196 int32_t* resultLength
,
199 return THIS(en
)->next(resultLength
, *ec
);
203 * Wrapper API to make StringEnumeration look like UEnumeration.
205 static void U_CALLCONV
206 ustrenum_reset(UEnumeration
* en
,
209 THIS(en
)->reset(*ec
);
213 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
214 * The StringEnumeration pointer will be stored in 'context'.
216 static const UEnumeration USTRENUM_VT
= {
218 NULL
, // store StringEnumeration pointer here
229 * Given a StringEnumeration, wrap it in a UEnumeration. The
230 * StringEnumeration is adopted; after this call, the caller must not
231 * delete it (regardless of error status).
233 U_CAPI UEnumeration
* U_EXPORT2
234 uenum_openStringEnumeration(StringEnumeration
* adopted
, UErrorCode
* ec
) {
235 UEnumeration
* result
= NULL
;
236 if (U_SUCCESS(*ec
) && adopted
!= NULL
) {
237 result
= (UEnumeration
*) uprv_malloc(sizeof(UEnumeration
));
238 if (result
== NULL
) {
239 *ec
= U_MEMORY_ALLOCATION_ERROR
;
241 uprv_memcpy(result
, &USTRENUM_VT
, sizeof(USTRENUM_VT
));
242 result
->context
= adopted
;
245 if (result
== NULL
) {
251 // C wrapper --------------------------------------------------------------- ***
255 typedef struct UCharStringEnumeration
{
257 int32_t index
, count
;
258 } UCharStringEnumeration
;
260 static void U_CALLCONV
261 ucharstrenum_close(UEnumeration
* en
) {
265 static int32_t U_CALLCONV
266 ucharstrenum_count(UEnumeration
* en
,
267 UErrorCode
* /*ec*/) {
268 return ((UCharStringEnumeration
*)en
)->count
;
271 static const char* U_CALLCONV
272 ucharstrenum_next(UEnumeration
* en
,
273 int32_t* resultLength
,
274 UErrorCode
* /*ec*/) {
275 UCharStringEnumeration
*e
= (UCharStringEnumeration
*) en
;
276 if (e
->index
>= e
->count
) {
279 const char* result
= ((const char**)e
->uenum
.context
)[e
->index
++];
281 *resultLength
= (int32_t)uprv_strlen(result
);
286 static void U_CALLCONV
287 ucharstrenum_reset(UEnumeration
* en
,
288 UErrorCode
* /*ec*/) {
289 ((UCharStringEnumeration
*)en
)->index
= 0;
292 static const UEnumeration UCHARSTRENUM_VT
= {
294 NULL
, // store StringEnumeration pointer here
304 U_CAPI UEnumeration
* U_EXPORT2
305 uenum_openCharStringsEnumeration(const char** strings
, int32_t count
,
307 UCharStringEnumeration
* result
= NULL
;
308 if (U_SUCCESS(*ec
) && count
>= 0 && (count
== 0 || strings
!= 0)) {
309 result
= (UCharStringEnumeration
*) uprv_malloc(sizeof(UCharStringEnumeration
));
310 if (result
== NULL
) {
311 *ec
= U_MEMORY_ALLOCATION_ERROR
;
313 U_ASSERT((char*)result
==(char*)(&result
->uenum
));
314 uprv_memcpy(result
, &UCHARSTRENUM_VT
, sizeof(UCHARSTRENUM_VT
));
315 result
->uenum
.context
= strings
;
317 result
->count
= count
;
320 return (UEnumeration
*) result
;