Coverage Report

Created: 2025-06-24 06:43

/src/icu/source/common/uenum.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
*
6
*   Copyright (C) 2002-2012, International Business Machines
7
*   Corporation and others.  All Rights Reserved.
8
*
9
*******************************************************************************
10
*   file name:  uenum.c
11
*   encoding:   UTF-8
12
*   tab size:   8 (not used)
13
*   indentation:2
14
*
15
*   created on: 2002jul08
16
*   created by: Vladimir Weinstein
17
*/
18
19
#include "unicode/putil.h"
20
#include "uenumimp.h"
21
#include "cmemory.h"
22
23
/* Layout of the baseContext buffer. */
24
typedef struct {
25
    int32_t len;  /* number of bytes available starting at 'data' */
26
    char    data; /* actual data starts here */
27
} _UEnumBuffer;
28
29
/* Extra bytes to allocate in the baseContext buffer. */
30
static const int32_t PAD = 8;
31
32
/* Return a pointer to the baseContext buffer, possibly allocating
33
   or reallocating it if at least 'capacity' bytes are not available. */
34
0
static void* _getBuffer(UEnumeration* en, int32_t capacity) {
35
36
0
    if (en->baseContext != NULL) {
37
0
        if (((_UEnumBuffer*) en->baseContext)->len < capacity) {
38
0
            capacity += PAD;
39
0
            en->baseContext = uprv_realloc(en->baseContext,
40
0
                                           sizeof(int32_t) + capacity);
41
0
            if (en->baseContext == NULL) {
42
0
                return NULL;
43
0
            }
44
0
            ((_UEnumBuffer*) en->baseContext)->len = capacity;
45
0
        }
46
0
    } else {
47
0
        capacity += PAD;
48
0
        en->baseContext = uprv_malloc(sizeof(int32_t) + capacity);
49
0
        if (en->baseContext == NULL) {
50
0
            return NULL;
51
0
        }
52
0
        ((_UEnumBuffer*) en->baseContext)->len = capacity;
53
0
    }
54
    
55
0
    return (void*) & ((_UEnumBuffer*) en->baseContext)->data;
56
0
}
57
58
U_CAPI void U_EXPORT2
59
uenum_close(UEnumeration* en)
60
0
{
61
0
    if (en) {
62
0
        if (en->close != NULL) {
63
0
            if (en->baseContext) {
64
0
                uprv_free(en->baseContext);
65
0
            }
66
0
            en->close(en);
67
0
        } else { /* this seems dangerous, but we better kill the object */
68
0
            uprv_free(en);
69
0
        }
70
0
    }
71
0
}
72
73
U_CAPI int32_t U_EXPORT2
74
uenum_count(UEnumeration* en, UErrorCode* status)
75
0
{
76
0
    if (!en || U_FAILURE(*status)) {
77
0
        return -1;
78
0
    }
79
0
    if (en->count != NULL) {
80
0
        return en->count(en, status);
81
0
    } else {
82
0
        *status = U_UNSUPPORTED_ERROR;
83
0
        return -1;
84
0
    }
85
0
}
86
87
/* Don't call this directly. Only uenum_unext should be calling this. */
88
U_CAPI const UChar* U_EXPORT2
89
uenum_unextDefault(UEnumeration* en,
90
            int32_t* resultLength,
91
            UErrorCode* status)
92
0
{
93
0
    UChar *ustr = NULL;
94
0
    int32_t len = 0;
95
0
    if (en->next != NULL) {
96
0
        const char *cstr = en->next(en, &len, status);
97
0
        if (cstr != NULL) {
98
0
            ustr = (UChar*) _getBuffer(en, (len+1) * sizeof(UChar));
99
0
            if (ustr == NULL) {
100
0
                *status = U_MEMORY_ALLOCATION_ERROR;
101
0
            } else {
102
0
                u_charsToUChars(cstr, ustr, len+1);
103
0
            }
104
0
        }
105
0
    } else {
106
0
        *status = U_UNSUPPORTED_ERROR;
107
0
    }
108
0
    if (resultLength) {
109
0
        *resultLength = len;
110
0
    }
111
0
    return ustr;
112
0
}
113
114
/* Don't call this directly. Only uenum_next should be calling this. */
115
U_CAPI const char* U_EXPORT2
116
uenum_nextDefault(UEnumeration* en,
117
            int32_t* resultLength,
118
            UErrorCode* status)
119
0
{
120
0
    if (en->uNext != NULL) {
121
0
        char *tempCharVal;
122
0
        const UChar *tempUCharVal = en->uNext(en, resultLength, status);
123
0
        if (tempUCharVal == NULL) {
124
0
            return NULL;
125
0
        }
126
0
        tempCharVal = (char*)
127
0
            _getBuffer(en, (*resultLength+1) * sizeof(char));
128
0
        if (!tempCharVal) {
129
0
            *status = U_MEMORY_ALLOCATION_ERROR;
130
0
            return NULL;
131
0
        }
132
0
        u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength + 1);
133
0
        return tempCharVal;
134
0
    } else {
135
0
        *status = U_UNSUPPORTED_ERROR;
136
0
        return NULL;
137
0
    }
138
0
}
139
140
U_CAPI const UChar* U_EXPORT2
141
uenum_unext(UEnumeration* en,
142
            int32_t* resultLength,
143
            UErrorCode* status)
144
0
{
145
0
    if (!en || U_FAILURE(*status)) {
146
0
        return NULL;
147
0
    }
148
0
    if (en->uNext != NULL) {
149
0
        return en->uNext(en, resultLength, status);
150
0
    } else {
151
0
        *status = U_UNSUPPORTED_ERROR;
152
0
        return NULL;
153
0
    }
154
0
}
155
156
U_CAPI const char* U_EXPORT2
157
uenum_next(UEnumeration* en,
158
          int32_t* resultLength,
159
          UErrorCode* status)
160
0
{
161
0
    if (!en || U_FAILURE(*status)) {
162
0
        return NULL;
163
0
    }
164
0
    if (en->next != NULL) {
165
0
        if (resultLength != NULL) {
166
0
            return en->next(en, resultLength, status);
167
0
        }
168
0
        else {
169
0
            int32_t dummyLength=0;
170
0
            return en->next(en, &dummyLength, status);
171
0
        }
172
0
    } else {
173
0
        *status = U_UNSUPPORTED_ERROR;
174
0
        return NULL;
175
0
    }
176
0
}
177
178
U_CAPI void U_EXPORT2
179
uenum_reset(UEnumeration* en, UErrorCode* status)
180
0
{
181
0
    if (!en || U_FAILURE(*status)) {
182
0
        return;
183
0
    }
184
0
    if (en->reset != NULL) {
185
0
        en->reset(en, status);
186
0
    } else {
187
0
        *status = U_UNSUPPORTED_ERROR;
188
0
    }
189
0
}