]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/ustrenum.cpp
ICU-8.11.tar.gz
[apple/icu.git] / icuSources / common / ustrenum.cpp
1 /*
2 **********************************************************************
3 * Copyright (c) 2002-2005, International Business Machines
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"
13 #include "unicode/putil.h"
14 #include "uenumimp.h"
15 #include "ustrenum.h"
16 #include "cstring.h"
17 #include "cmemory.h"
18 #include "uassert.h"
19
20 U_NAMESPACE_BEGIN
21 // StringEnumeration implementation ---------------------------------------- ***
22
23 StringEnumeration::StringEnumeration()
24 : chars(charsBuffer), charsCapacity(sizeof(charsBuffer)) {
25 }
26
27 StringEnumeration::~StringEnumeration() {
28 if (chars != NULL && chars != charsBuffer) {
29 uprv_free(chars);
30 }
31 }
32
33 // StringEnumeration base class clone() default implementation, does not clone
34 StringEnumeration *
35 StringEnumeration::clone() const {
36 return NULL;
37 }
38
39 const char *
40 StringEnumeration::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
57 const UChar *
58 StringEnumeration::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
73 void
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;
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
94 UnicodeString *
95 StringEnumeration::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 }
114 UBool
115 StringEnumeration::operator==(const StringEnumeration& that)const {
116 return getDynamicClassID() == that.getDynamicClassID();
117 }
118
119 UBool
120 StringEnumeration::operator!=(const StringEnumeration& that)const {
121 return !operator==(that);
122 }
123
124 // UStringEnumeration implementation --------------------------------------- ***
125
126 UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
127 uenum(_uenum) {
128 U_ASSERT(_uenum != 0);
129 }
130
131 UStringEnumeration::~UStringEnumeration() {
132 uenum_close(uenum);
133 }
134
135 int32_t UStringEnumeration::count(UErrorCode& status) const {
136 return uenum_count(uenum, &status);
137 }
138
139 const 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
148 void UStringEnumeration::reset(UErrorCode& status) {
149 uenum_reset(uenum, &status);
150 }
151
152 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration/*, StringEnumeration*/)
153 U_NAMESPACE_END
154
155 // C wrapper --------------------------------------------------------------- ***
156
157 #define THIS(en) ((StringEnumeration*)(en->context))
158
159 U_CDECL_BEGIN
160
161 /**
162 * Wrapper API to make StringEnumeration look like UEnumeration.
163 */
164 static void U_CALLCONV
165 ustrenum_close(UEnumeration* en) {
166 delete THIS(en);
167 uprv_free(en);
168 }
169
170 /**
171 * Wrapper API to make StringEnumeration look like UEnumeration.
172 */
173 static int32_t U_CALLCONV
174 ustrenum_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 */
183 static const UChar* U_CALLCONV
184 ustrenum_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 */
194 static const char* U_CALLCONV
195 ustrenum_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 */
205 static void U_CALLCONV
206 ustrenum_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 */
216 static const UEnumeration USTRENUM_VT = {
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
226 U_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 */
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;
240 } else {
241 uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
242 result->context = adopted;
243 }
244 }
245 if (result == NULL) {
246 delete adopted;
247 }
248 return result;
249 }
250
251 // C wrapper --------------------------------------------------------------- ***
252
253 U_CDECL_BEGIN
254
255 typedef struct UCharStringEnumeration {
256 UEnumeration uenum;
257 int32_t index, count;
258 } UCharStringEnumeration;
259
260 static void U_CALLCONV
261 ucharstrenum_close(UEnumeration* en) {
262 uprv_free(en);
263 }
264
265 static int32_t U_CALLCONV
266 ucharstrenum_count(UEnumeration* en,
267 UErrorCode* /*ec*/) {
268 return ((UCharStringEnumeration*)en)->count;
269 }
270
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) {
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
286 static void U_CALLCONV
287 ucharstrenum_reset(UEnumeration* en,
288 UErrorCode* /*ec*/) {
289 ((UCharStringEnumeration*)en)->index = 0;
290 }
291
292 static 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
302 U_CDECL_END
303
304 U_CAPI UEnumeration* U_EXPORT2
305 uenum_openCharStringsEnumeration(const char** strings, int32_t count,
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));
315 result->uenum.context = strings;
316 result->index = 0;
317 result->count = count;
318 }
319 }
320 return (UEnumeration*) result;
321 }
322
323