Coverage Report

Created: 2026-03-31 06:12

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/icu/icu4c/source/common/uenum.cpp
Line
Count
Source
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 != nullptr) {
37
0
        if (static_cast<_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 == nullptr) {
42
0
                return nullptr;
43
0
            }
44
0
            static_cast<_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 == nullptr) {
50
0
            return nullptr;
51
0
        }
52
0
        static_cast<_UEnumBuffer*>(en->baseContext)->len = capacity;
53
0
    }
54
    
55
0
    return static_cast<void*>(&static_cast<_UEnumBuffer*>(en->baseContext)->data);
56
0
}
57
58
U_CAPI void U_EXPORT2
59
uenum_close(UEnumeration* en)
60
10.8k
{
61
10.8k
    if (en) {
62
9.19k
        if (en->close != nullptr) {
63
9.19k
            if (en->baseContext) {
64
0
                uprv_free(en->baseContext);
65
0
            }
66
9.19k
            en->close(en);
67
9.19k
        } else { /* this seems dangerous, but we better kill the object */
68
0
            uprv_free(en);
69
0
        }
70
9.19k
    }
71
10.8k
}
72
73
U_CAPI int32_t U_EXPORT2
74
uenum_count(UEnumeration* en, UErrorCode* status)
75
5.71k
{
76
5.71k
    if (!en || U_FAILURE(*status)) {
77
0
        return -1;
78
0
    }
79
5.71k
    if (en->count != nullptr) {
80
5.71k
        return en->count(en, status);
81
5.71k
    } else {
82
0
        *status = U_UNSUPPORTED_ERROR;
83
0
        return -1;
84
0
    }
85
5.71k
}
86
87
/* Don't call this directly. Only uenum_unext should be calling this. */
88
U_CAPI const char16_t* U_EXPORT2
89
uenum_unextDefault(UEnumeration* en,
90
            int32_t* resultLength,
91
            UErrorCode* status)
92
0
{
93
0
    char16_t *ustr = nullptr;
94
0
    int32_t len = 0;
95
0
    if (en->next != nullptr) {
96
0
        const char *cstr = en->next(en, &len, status);
97
0
        if (cstr != nullptr) {
98
0
            ustr = (char16_t*) _getBuffer(en, (len+1) * sizeof(char16_t));
99
0
            if (ustr == nullptr) {
100
0
                *status = U_MEMORY_ALLOCATION_ERROR;
101
0
            } else {
102
0
                u_charsToUChars(cstr, ustr, len);
103
0
                ustr[len] = 0;
104
0
            }
105
0
        }
106
0
    } else {
107
0
        *status = U_UNSUPPORTED_ERROR;
108
0
    }
109
0
    if (resultLength) {
110
0
        *resultLength = len;
111
0
    }
112
0
    return ustr;
113
0
}
114
115
/* Don't call this directly. Only uenum_next should be calling this. */
116
U_CAPI const char* U_EXPORT2
117
uenum_nextDefault(UEnumeration* en,
118
            int32_t* resultLength,
119
            UErrorCode* status)
120
0
{
121
0
    if (en->uNext != nullptr) {
122
0
        char *tempCharVal;
123
0
        const char16_t *tempUCharVal = en->uNext(en, resultLength, status);
124
0
        if (tempUCharVal == nullptr) {
125
0
            return nullptr;
126
0
        }
127
0
        tempCharVal = (char*)
128
0
            _getBuffer(en, (*resultLength+1) * sizeof(char));
129
0
        if (!tempCharVal) {
130
0
            *status = U_MEMORY_ALLOCATION_ERROR;
131
0
            return nullptr;
132
0
        }
133
0
        u_UCharsToChars(tempUCharVal, tempCharVal, *resultLength);
134
0
        tempCharVal[*resultLength] = 0;
135
0
        return tempCharVal;
136
0
    } else {
137
0
        *status = U_UNSUPPORTED_ERROR;
138
0
        return nullptr;
139
0
    }
140
0
}
141
142
U_CAPI const char16_t* U_EXPORT2
143
uenum_unext(UEnumeration* en,
144
            int32_t* resultLength,
145
            UErrorCode* status)
146
0
{
147
0
    if (!en || U_FAILURE(*status)) {
148
0
        return nullptr;
149
0
    }
150
0
    if (en->uNext != nullptr) {
151
0
        return en->uNext(en, resultLength, status);
152
0
    } else {
153
0
        *status = U_UNSUPPORTED_ERROR;
154
0
        return nullptr;
155
0
    }
156
0
}
157
158
U_CAPI const char* U_EXPORT2
159
uenum_next(UEnumeration* en,
160
          int32_t* resultLength,
161
          UErrorCode* status)
162
47.0k
{
163
47.0k
    if (!en || U_FAILURE(*status)) {
164
6
        return nullptr;
165
6
    }
166
47.0k
    if (en->next != nullptr) {
167
47.0k
        if (resultLength != nullptr) {
168
797
            return en->next(en, resultLength, status);
169
797
        }
170
46.2k
        else {
171
46.2k
            int32_t dummyLength=0;
172
46.2k
            return en->next(en, &dummyLength, status);
173
46.2k
        }
174
47.0k
    } else {
175
0
        *status = U_UNSUPPORTED_ERROR;
176
0
        return nullptr;
177
0
    }
178
47.0k
}
179
180
U_CAPI void U_EXPORT2
181
uenum_reset(UEnumeration* en, UErrorCode* status)
182
0
{
183
0
    if (!en || U_FAILURE(*status)) {
184
0
        return;
185
0
    }
186
0
    if (en->reset != nullptr) {
187
0
        en->reset(en, status);
188
0
    } else {
189
0
        *status = U_UNSUPPORTED_ERROR;
190
0
    }
191
0
}