]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/ustrenum.cpp
ICU-57166.0.1.tar.gz
[apple/icu.git] / icuSources / common / ustrenum.cpp
CommitLineData
b75a7d8f
A
1/*
2**********************************************************************
b331163b 3* Copyright (c) 2002-2014, International Business Machines
b75a7d8f
A
4* Corporation and others. All Rights Reserved.
5**********************************************************************
6* Author: Alan Liu
7* Created: November 11 2002
8* Since: ICU 2.4
9**********************************************************************
10*/
51004dcb 11#include "utypeinfo.h" // for 'typeid' to work
729e4ab9 12
b75a7d8f
A
13#include "unicode/ustring.h"
14#include "unicode/strenum.h"
374ca955 15#include "unicode/putil.h"
b75a7d8f
A
16#include "uenumimp.h"
17#include "ustrenum.h"
18#include "cstring.h"
19#include "cmemory.h"
374ca955
A
20#include "uassert.h"
21
22U_NAMESPACE_BEGIN
23// StringEnumeration implementation ---------------------------------------- ***
24
25StringEnumeration::StringEnumeration()
26 : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
27}
28
29StringEnumeration::~StringEnumeration() {
30 if (chars != NULL && chars != charsBuffer) {
31 uprv_free(chars);
32 }
33}
34
35// StringEnumeration base class clone() default implementation, does not clone
36StringEnumeration *
37StringEnumeration::clone() const {
38 return NULL;
39}
40
41const char *
42StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
43 const UnicodeString *s=snext(status);
51004dcb 44 if(U_SUCCESS(status) && s!=NULL) {
374ca955
A
45 unistr=*s;
46 ensureCharsCapacity(unistr.length()+1, status);
47 if(U_SUCCESS(status)) {
48 if(resultLength!=NULL) {
49 *resultLength=unistr.length();
50 }
51 unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV);
52 return chars;
53 }
54 }
55
56 return NULL;
57}
58
59const UChar *
60StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
61 const UnicodeString *s=snext(status);
51004dcb 62 if(U_SUCCESS(status) && s!=NULL) {
374ca955 63 unistr=*s;
51004dcb
A
64 if(resultLength!=NULL) {
65 *resultLength=unistr.length();
374ca955 66 }
51004dcb 67 return unistr.getTerminatedBuffer();
374ca955
A
68 }
69
70 return NULL;
71}
72
51004dcb
A
73const UnicodeString *
74StringEnumeration::snext(UErrorCode &status) {
75 int32_t length;
76 const char *s=next(&length, status);
77 return setChars(s, length, status);
78}
79
374ca955
A
80void
81StringEnumeration::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;
86 }
87 if(chars!=charsBuffer) {
88 uprv_free(chars);
89 }
90 chars=(char *)uprv_malloc(capacity);
91 if(chars==NULL) {
92 chars=charsBuffer;
93 charsCapacity=sizeof(charsBuffer);
94 status=U_MEMORY_ALLOCATION_ERROR;
95 } else {
96 charsCapacity=capacity;
97 }
98 }
99}
100
101UnicodeString *
102StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
103 if(U_SUCCESS(status) && s!=NULL) {
104 if(length<0) {
105 length=(int32_t)uprv_strlen(s);
106 }
107
108 UChar *buffer=unistr.getBuffer(length+1);
109 if(buffer!=NULL) {
110 u_charsToUChars(s, buffer, length);
111 buffer[length]=0;
112 unistr.releaseBuffer(length);
113 return &unistr;
114 } else {
115 status=U_MEMORY_ALLOCATION_ERROR;
116 }
117 }
118
119 return NULL;
120}
73c04bcf
A
121UBool
122StringEnumeration::operator==(const StringEnumeration& that)const {
729e4ab9 123 return typeid(*this) == typeid(that);
73c04bcf
A
124}
125
126UBool
127StringEnumeration::operator!=(const StringEnumeration& that)const {
128 return !operator==(that);
129}
374ca955
A
130
131// UStringEnumeration implementation --------------------------------------- ***
132
b331163b
A
133UStringEnumeration * U_EXPORT2
134UStringEnumeration::fromUEnumeration(
135 UEnumeration *uenumToAdopt, UErrorCode &status) {
136 if (U_FAILURE(status)) {
137 uenum_close(uenumToAdopt);
138 return NULL;
139 }
140 UStringEnumeration *result = new UStringEnumeration(uenumToAdopt);
141 if (result == NULL) {
142 status = U_MEMORY_ALLOCATION_ERROR;
143 uenum_close(uenumToAdopt);
144 return NULL;
145 }
146 return result;
147}
148
374ca955
A
149UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
150 uenum(_uenum) {
151 U_ASSERT(_uenum != 0);
152}
153
154UStringEnumeration::~UStringEnumeration() {
155 uenum_close(uenum);
156}
157
158int32_t UStringEnumeration::count(UErrorCode& status) const {
159 return uenum_count(uenum, &status);
160}
161
51004dcb
A
162const char *UStringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
163 return uenum_next(uenum, resultLength, &status);
164}
165
374ca955
A
166const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
167 int32_t length;
168 const UChar* str = uenum_unext(uenum, &length, &status);
169 if (str == 0 || U_FAILURE(status)) {
170 return 0;
171 }
172 return &unistr.setTo(str, length);
173}
174
175void UStringEnumeration::reset(UErrorCode& status) {
176 uenum_reset(uenum, &status);
177}
178
46f4442e 179UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration)
374ca955
A
180U_NAMESPACE_END
181
182// C wrapper --------------------------------------------------------------- ***
b75a7d8f 183
4388f060 184#define THIS(en) ((icu::StringEnumeration*)(en->context))
b75a7d8f
A
185
186U_CDECL_BEGIN
187
188/**
189 * Wrapper API to make StringEnumeration look like UEnumeration.
190 */
191static void U_CALLCONV
192ustrenum_close(UEnumeration* en) {
193 delete THIS(en);
194 uprv_free(en);
195}
196
197/**
198 * Wrapper API to make StringEnumeration look like UEnumeration.
199 */
200static int32_t U_CALLCONV
201ustrenum_count(UEnumeration* en,
202 UErrorCode* ec)
203{
204 return THIS(en)->count(*ec);
205}
206
207/**
208 * Wrapper API to make StringEnumeration look like UEnumeration.
209 */
210static const UChar* U_CALLCONV
211ustrenum_unext(UEnumeration* en,
212 int32_t* resultLength,
213 UErrorCode* ec)
214{
215 return THIS(en)->unext(resultLength, *ec);
216}
217
218/**
219 * Wrapper API to make StringEnumeration look like UEnumeration.
220 */
221static const char* U_CALLCONV
222ustrenum_next(UEnumeration* en,
223 int32_t* resultLength,
224 UErrorCode* ec)
225{
226 return THIS(en)->next(resultLength, *ec);
227}
228
229/**
230 * Wrapper API to make StringEnumeration look like UEnumeration.
231 */
232static void U_CALLCONV
233ustrenum_reset(UEnumeration* en,
234 UErrorCode* ec)
235{
236 THIS(en)->reset(*ec);
237}
238
239/**
240 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
241 * The StringEnumeration pointer will be stored in 'context'.
242 */
374ca955 243static const UEnumeration USTRENUM_VT = {
b75a7d8f
A
244 NULL,
245 NULL, // store StringEnumeration pointer here
246 ustrenum_close,
247 ustrenum_count,
248 ustrenum_unext,
249 ustrenum_next,
250 ustrenum_reset
251};
252
253U_CDECL_END
254
255/**
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).
259 */
260U_CAPI UEnumeration* U_EXPORT2
4388f060 261uenum_openFromStringEnumeration(icu::StringEnumeration* adopted, UErrorCode* ec) {
b75a7d8f
A
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;
267 } else {
374ca955 268 uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
b75a7d8f
A
269 result->context = adopted;
270 }
271 }
272 if (result == NULL) {
273 delete adopted;
274 }
275 return result;
276}
277
374ca955
A
278// C wrapper --------------------------------------------------------------- ***
279
280U_CDECL_BEGIN
281
282typedef struct UCharStringEnumeration {
283 UEnumeration uenum;
284 int32_t index, count;
285} UCharStringEnumeration;
286
287static void U_CALLCONV
288ucharstrenum_close(UEnumeration* en) {
289 uprv_free(en);
290}
291
292static int32_t U_CALLCONV
293ucharstrenum_count(UEnumeration* en,
294 UErrorCode* /*ec*/) {
295 return ((UCharStringEnumeration*)en)->count;
296}
297
51004dcb
A
298static const UChar* U_CALLCONV
299ucharstrenum_unext(UEnumeration* en,
300 int32_t* resultLength,
301 UErrorCode* /*ec*/) {
302 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
303 if (e->index >= e->count) {
304 return NULL;
305 }
306 const UChar* result = ((const UChar**)e->uenum.context)[e->index++];
307 if (resultLength) {
308 *resultLength = (int32_t)u_strlen(result);
309 }
310 return result;
311}
312
313
374ca955
A
314static const char* U_CALLCONV
315ucharstrenum_next(UEnumeration* en,
316 int32_t* resultLength,
317 UErrorCode* /*ec*/) {
318 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
319 if (e->index >= e->count) {
320 return NULL;
321 }
322 const char* result = ((const char**)e->uenum.context)[e->index++];
323 if (resultLength) {
324 *resultLength = (int32_t)uprv_strlen(result);
325 }
326 return result;
327}
328
329static void U_CALLCONV
330ucharstrenum_reset(UEnumeration* en,
331 UErrorCode* /*ec*/) {
332 ((UCharStringEnumeration*)en)->index = 0;
333}
334
335static const UEnumeration UCHARSTRENUM_VT = {
336 NULL,
337 NULL, // store StringEnumeration pointer here
338 ucharstrenum_close,
339 ucharstrenum_count,
340 uenum_unextDefault,
341 ucharstrenum_next,
342 ucharstrenum_reset
343};
344
51004dcb
A
345static const UEnumeration UCHARSTRENUM_U_VT = {
346 NULL,
347 NULL, // store StringEnumeration pointer here
348 ucharstrenum_close,
349 ucharstrenum_count,
350 ucharstrenum_unext,
351 uenum_nextDefault,
352 ucharstrenum_reset
353};
354
374ca955
A
355U_CDECL_END
356
357U_CAPI UEnumeration* U_EXPORT2
51004dcb 358uenum_openCharStringsEnumeration(const char* const strings[], int32_t count,
374ca955
A
359 UErrorCode* ec) {
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;
365 } else {
366 U_ASSERT((char*)result==(char*)(&result->uenum));
367 uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
46f4442e 368 result->uenum.context = (void*)strings;
374ca955
A
369 result->index = 0;
370 result->count = count;
371 }
372 }
373 return (UEnumeration*) result;
374}
375
51004dcb
A
376U_CAPI UEnumeration* U_EXPORT2
377uenum_openUCharStringsEnumeration(const UChar* const strings[], int32_t count,
378 UErrorCode* ec) {
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;
384 } else {
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;
388 result->index = 0;
389 result->count = count;
390 }
391 }
392 return (UEnumeration*) result;
393}
394
73c04bcf 395
51004dcb 396// end C Wrapper