]> git.saurik.com Git - apple/icu.git/blame - icuSources/common/ustrenum.cpp
ICU-400.42.tar.gz
[apple/icu.git] / icuSources / common / ustrenum.cpp
CommitLineData
b75a7d8f
A
1/*
2**********************************************************************
46f4442e 3* Copyright (c) 2002-2008, 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*/
11#include "unicode/ustring.h"
12#include "unicode/strenum.h"
374ca955 13#include "unicode/putil.h"
b75a7d8f
A
14#include "uenumimp.h"
15#include "ustrenum.h"
16#include "cstring.h"
17#include "cmemory.h"
374ca955
A
18#include "uassert.h"
19
20U_NAMESPACE_BEGIN
21// StringEnumeration implementation ---------------------------------------- ***
22
23StringEnumeration::StringEnumeration()
24 : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
25}
26
27StringEnumeration::~StringEnumeration() {
28 if (chars != NULL && chars != charsBuffer) {
29 uprv_free(chars);
30 }
31}
32
33// StringEnumeration base class clone() default implementation, does not clone
34StringEnumeration *
35StringEnumeration::clone() const {
36 return NULL;
37}
38
39const char *
40StringEnumeration::next(int32_t *resultLength, UErrorCode &status) {
41 const UnicodeString *s=snext(status);
42 if(s!=NULL) {
43 unistr=*s;
44 ensureCharsCapacity(unistr.length()+1, status);
45 if(U_SUCCESS(status)) {
46 if(resultLength!=NULL) {
47 *resultLength=unistr.length();
48 }
49 unistr.extract(0, INT32_MAX, chars, charsCapacity, US_INV);
50 return chars;
51 }
52 }
53
54 return NULL;
55}
56
57const UChar *
58StringEnumeration::unext(int32_t *resultLength, UErrorCode &status) {
59 const UnicodeString *s=snext(status);
60 if(s!=NULL) {
61 unistr=*s;
62 if(U_SUCCESS(status)) {
63 if(resultLength!=NULL) {
64 *resultLength=unistr.length();
65 }
66 return unistr.getTerminatedBuffer();
67 }
68 }
69
70 return NULL;
71}
72
73void
74StringEnumeration::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;
79 }
80 if(chars!=charsBuffer) {
81 uprv_free(chars);
82 }
83 chars=(char *)uprv_malloc(capacity);
84 if(chars==NULL) {
85 chars=charsBuffer;
86 charsCapacity=sizeof(charsBuffer);
87 status=U_MEMORY_ALLOCATION_ERROR;
88 } else {
89 charsCapacity=capacity;
90 }
91 }
92}
93
94UnicodeString *
95StringEnumeration::setChars(const char *s, int32_t length, UErrorCode &status) {
96 if(U_SUCCESS(status) && s!=NULL) {
97 if(length<0) {
98 length=(int32_t)uprv_strlen(s);
99 }
100
101 UChar *buffer=unistr.getBuffer(length+1);
102 if(buffer!=NULL) {
103 u_charsToUChars(s, buffer, length);
104 buffer[length]=0;
105 unistr.releaseBuffer(length);
106 return &unistr;
107 } else {
108 status=U_MEMORY_ALLOCATION_ERROR;
109 }
110 }
111
112 return NULL;
113}
73c04bcf
A
114UBool
115StringEnumeration::operator==(const StringEnumeration& that)const {
116 return getDynamicClassID() == that.getDynamicClassID();
117}
118
119UBool
120StringEnumeration::operator!=(const StringEnumeration& that)const {
121 return !operator==(that);
122}
374ca955
A
123
124// UStringEnumeration implementation --------------------------------------- ***
125
126UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
127 uenum(_uenum) {
128 U_ASSERT(_uenum != 0);
129}
130
131UStringEnumeration::~UStringEnumeration() {
132 uenum_close(uenum);
133}
134
135int32_t UStringEnumeration::count(UErrorCode& status) const {
136 return uenum_count(uenum, &status);
137}
138
139const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
140 int32_t length;
141 const UChar* str = uenum_unext(uenum, &length, &status);
142 if (str == 0 || U_FAILURE(status)) {
143 return 0;
144 }
145 return &unistr.setTo(str, length);
146}
147
148void UStringEnumeration::reset(UErrorCode& status) {
149 uenum_reset(uenum, &status);
150}
151
46f4442e 152UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration)
374ca955
A
153U_NAMESPACE_END
154
155// C wrapper --------------------------------------------------------------- ***
b75a7d8f 156
46f4442e 157#define THIS(en) ((U_NAMESPACE_QUALIFIER StringEnumeration*)(en->context))
b75a7d8f
A
158
159U_CDECL_BEGIN
160
161/**
162 * Wrapper API to make StringEnumeration look like UEnumeration.
163 */
164static void U_CALLCONV
165ustrenum_close(UEnumeration* en) {
166 delete THIS(en);
167 uprv_free(en);
168}
169
170/**
171 * Wrapper API to make StringEnumeration look like UEnumeration.
172 */
173static int32_t U_CALLCONV
174ustrenum_count(UEnumeration* en,
175 UErrorCode* ec)
176{
177 return THIS(en)->count(*ec);
178}
179
180/**
181 * Wrapper API to make StringEnumeration look like UEnumeration.
182 */
183static const UChar* U_CALLCONV
184ustrenum_unext(UEnumeration* en,
185 int32_t* resultLength,
186 UErrorCode* ec)
187{
188 return THIS(en)->unext(resultLength, *ec);
189}
190
191/**
192 * Wrapper API to make StringEnumeration look like UEnumeration.
193 */
194static const char* U_CALLCONV
195ustrenum_next(UEnumeration* en,
196 int32_t* resultLength,
197 UErrorCode* ec)
198{
199 return THIS(en)->next(resultLength, *ec);
200}
201
202/**
203 * Wrapper API to make StringEnumeration look like UEnumeration.
204 */
205static void U_CALLCONV
206ustrenum_reset(UEnumeration* en,
207 UErrorCode* ec)
208{
209 THIS(en)->reset(*ec);
210}
211
212/**
213 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
214 * The StringEnumeration pointer will be stored in 'context'.
215 */
374ca955 216static const UEnumeration USTRENUM_VT = {
b75a7d8f
A
217 NULL,
218 NULL, // store StringEnumeration pointer here
219 ustrenum_close,
220 ustrenum_count,
221 ustrenum_unext,
222 ustrenum_next,
223 ustrenum_reset
224};
225
226U_CDECL_END
227
228/**
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).
232 */
233U_CAPI UEnumeration* U_EXPORT2
46f4442e 234uenum_openStringEnumeration(U_NAMESPACE_QUALIFIER StringEnumeration* adopted, UErrorCode* ec) {
b75a7d8f
A
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;
240 } else {
374ca955 241 uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
b75a7d8f
A
242 result->context = adopted;
243 }
244 }
245 if (result == NULL) {
246 delete adopted;
247 }
248 return result;
249}
250
374ca955
A
251// C wrapper --------------------------------------------------------------- ***
252
253U_CDECL_BEGIN
254
255typedef struct UCharStringEnumeration {
256 UEnumeration uenum;
257 int32_t index, count;
258} UCharStringEnumeration;
259
260static void U_CALLCONV
261ucharstrenum_close(UEnumeration* en) {
262 uprv_free(en);
263}
264
265static int32_t U_CALLCONV
266ucharstrenum_count(UEnumeration* en,
267 UErrorCode* /*ec*/) {
268 return ((UCharStringEnumeration*)en)->count;
269}
270
271static const char* U_CALLCONV
272ucharstrenum_next(UEnumeration* en,
273 int32_t* resultLength,
274 UErrorCode* /*ec*/) {
275 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
276 if (e->index >= e->count) {
277 return NULL;
278 }
279 const char* result = ((const char**)e->uenum.context)[e->index++];
280 if (resultLength) {
281 *resultLength = (int32_t)uprv_strlen(result);
282 }
283 return result;
284}
285
286static void U_CALLCONV
287ucharstrenum_reset(UEnumeration* en,
288 UErrorCode* /*ec*/) {
289 ((UCharStringEnumeration*)en)->index = 0;
290}
291
292static const UEnumeration UCHARSTRENUM_VT = {
293 NULL,
294 NULL, // store StringEnumeration pointer here
295 ucharstrenum_close,
296 ucharstrenum_count,
297 uenum_unextDefault,
298 ucharstrenum_next,
299 ucharstrenum_reset
300};
301
302U_CDECL_END
303
304U_CAPI UEnumeration* U_EXPORT2
46f4442e 305uenum_openCharStringsEnumeration(const char* const* strings, int32_t count,
374ca955
A
306 UErrorCode* ec) {
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;
312 } else {
313 U_ASSERT((char*)result==(char*)(&result->uenum));
314 uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
46f4442e 315 result->uenum.context = (void*)strings;
374ca955
A
316 result->index = 0;
317 result->count = count;
318 }
319 }
320 return (UEnumeration*) result;
321}
322
73c04bcf 323