Coverage Report

Created: 2021-08-22 09:07

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