]> git.saurik.com Git - apple/icu.git/blob - icuSources/common/ustrenum.cpp
ICU-6.2.4.tar.gz
[apple/icu.git] / icuSources / common / ustrenum.cpp
1 /*
2 **********************************************************************
3 * Copyright (c) 2002-2004, 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
115 // UStringEnumeration implementation --------------------------------------- ***
116
117 UStringEnumeration::UStringEnumeration(UEnumeration* _uenum) :
118 uenum(_uenum) {
119 U_ASSERT(_uenum != 0);
120 }
121
122 UStringEnumeration::~UStringEnumeration() {
123 uenum_close(uenum);
124 }
125
126 int32_t UStringEnumeration::count(UErrorCode& status) const {
127 return uenum_count(uenum, &status);
128 }
129
130 const UnicodeString* UStringEnumeration::snext(UErrorCode& status) {
131 int32_t length;
132 const UChar* str = uenum_unext(uenum, &length, &status);
133 if (str == 0 || U_FAILURE(status)) {
134 return 0;
135 }
136 return &unistr.setTo(str, length);
137 }
138
139 void UStringEnumeration::reset(UErrorCode& status) {
140 uenum_reset(uenum, &status);
141 }
142
143 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UStringEnumeration/*, StringEnumeration*/)
144 U_NAMESPACE_END
145
146 // C wrapper --------------------------------------------------------------- ***
147
148 #define THIS(en) ((StringEnumeration*)(en->context))
149
150 U_CDECL_BEGIN
151
152 /**
153 * Wrapper API to make StringEnumeration look like UEnumeration.
154 */
155 static void U_CALLCONV
156 ustrenum_close(UEnumeration* en) {
157 delete THIS(en);
158 uprv_free(en);
159 }
160
161 /**
162 * Wrapper API to make StringEnumeration look like UEnumeration.
163 */
164 static int32_t U_CALLCONV
165 ustrenum_count(UEnumeration* en,
166 UErrorCode* ec)
167 {
168 return THIS(en)->count(*ec);
169 }
170
171 /**
172 * Wrapper API to make StringEnumeration look like UEnumeration.
173 */
174 static const UChar* U_CALLCONV
175 ustrenum_unext(UEnumeration* en,
176 int32_t* resultLength,
177 UErrorCode* ec)
178 {
179 return THIS(en)->unext(resultLength, *ec);
180 }
181
182 /**
183 * Wrapper API to make StringEnumeration look like UEnumeration.
184 */
185 static const char* U_CALLCONV
186 ustrenum_next(UEnumeration* en,
187 int32_t* resultLength,
188 UErrorCode* ec)
189 {
190 return THIS(en)->next(resultLength, *ec);
191 }
192
193 /**
194 * Wrapper API to make StringEnumeration look like UEnumeration.
195 */
196 static void U_CALLCONV
197 ustrenum_reset(UEnumeration* en,
198 UErrorCode* ec)
199 {
200 THIS(en)->reset(*ec);
201 }
202
203 /**
204 * Pseudo-vtable for UEnumeration wrapper around StringEnumeration.
205 * The StringEnumeration pointer will be stored in 'context'.
206 */
207 static const UEnumeration USTRENUM_VT = {
208 NULL,
209 NULL, // store StringEnumeration pointer here
210 ustrenum_close,
211 ustrenum_count,
212 ustrenum_unext,
213 ustrenum_next,
214 ustrenum_reset
215 };
216
217 U_CDECL_END
218
219 /**
220 * Given a StringEnumeration, wrap it in a UEnumeration. The
221 * StringEnumeration is adopted; after this call, the caller must not
222 * delete it (regardless of error status).
223 */
224 U_CAPI UEnumeration* U_EXPORT2
225 uenum_openStringEnumeration(StringEnumeration* adopted, UErrorCode* ec) {
226 UEnumeration* result = NULL;
227 if (U_SUCCESS(*ec) && adopted != NULL) {
228 result = (UEnumeration*) uprv_malloc(sizeof(UEnumeration));
229 if (result == NULL) {
230 *ec = U_MEMORY_ALLOCATION_ERROR;
231 } else {
232 uprv_memcpy(result, &USTRENUM_VT, sizeof(USTRENUM_VT));
233 result->context = adopted;
234 }
235 }
236 if (result == NULL) {
237 delete adopted;
238 }
239 return result;
240 }
241
242 // C wrapper --------------------------------------------------------------- ***
243
244 U_CDECL_BEGIN
245
246 typedef struct UCharStringEnumeration {
247 UEnumeration uenum;
248 int32_t index, count;
249 } UCharStringEnumeration;
250
251 static void U_CALLCONV
252 ucharstrenum_close(UEnumeration* en) {
253 uprv_free(en);
254 }
255
256 static int32_t U_CALLCONV
257 ucharstrenum_count(UEnumeration* en,
258 UErrorCode* /*ec*/) {
259 return ((UCharStringEnumeration*)en)->count;
260 }
261
262 static const char* U_CALLCONV
263 ucharstrenum_next(UEnumeration* en,
264 int32_t* resultLength,
265 UErrorCode* /*ec*/) {
266 UCharStringEnumeration *e = (UCharStringEnumeration*) en;
267 if (e->index >= e->count) {
268 return NULL;
269 }
270 const char* result = ((const char**)e->uenum.context)[e->index++];
271 if (resultLength) {
272 *resultLength = (int32_t)uprv_strlen(result);
273 }
274 return result;
275 }
276
277 static void U_CALLCONV
278 ucharstrenum_reset(UEnumeration* en,
279 UErrorCode* /*ec*/) {
280 ((UCharStringEnumeration*)en)->index = 0;
281 }
282
283 static const UEnumeration UCHARSTRENUM_VT = {
284 NULL,
285 NULL, // store StringEnumeration pointer here
286 ucharstrenum_close,
287 ucharstrenum_count,
288 uenum_unextDefault,
289 ucharstrenum_next,
290 ucharstrenum_reset
291 };
292
293 U_CDECL_END
294
295 U_CAPI UEnumeration* U_EXPORT2
296 uenum_openCharStringsEnumeration(const char** strings, int32_t count,
297 UErrorCode* ec) {
298 UCharStringEnumeration* result = NULL;
299 if (U_SUCCESS(*ec) && count >= 0 && (count == 0 || strings != 0)) {
300 result = (UCharStringEnumeration*) uprv_malloc(sizeof(UCharStringEnumeration));
301 if (result == NULL) {
302 *ec = U_MEMORY_ALLOCATION_ERROR;
303 } else {
304 U_ASSERT((char*)result==(char*)(&result->uenum));
305 uprv_memcpy(result, &UCHARSTRENUM_VT, sizeof(UCHARSTRENUM_VT));
306 result->uenum.context = strings;
307 result->index = 0;
308 result->count = count;
309 }
310 }
311 return (UEnumeration*) result;
312 }
313