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/ulist.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
*   Copyright (C) 2009-2016, International Business Machines
6
*   Corporation and others.  All Rights Reserved.
7
******************************************************************************
8
*/
9
10
#include "ulist.h"
11
#include "cmemory.h"
12
#include "cstring.h"
13
#include "uenumimp.h"
14
15
typedef struct UListNode UListNode;
16
struct UListNode {
17
    void *data;
18
    
19
    UListNode *next;
20
    UListNode *previous;
21
    
22
    /* When data is created with uprv_malloc, needs to be freed during deleteList function. */
23
    UBool forceDelete;
24
};
25
26
struct UList {
27
    UListNode *curr;
28
    UListNode *head;
29
    UListNode *tail;
30
    
31
    int32_t size;
32
};
33
34
static void ulist_addFirstItem(UList *list, UListNode *newItem);
35
36
4.76k
U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) {
37
4.76k
    UList *newList = nullptr;
38
    
39
4.76k
    if (U_FAILURE(*status)) {
40
0
        return nullptr;
41
0
    }
42
    
43
4.76k
    newList = (UList *)uprv_malloc(sizeof(UList));
44
4.76k
    if (newList == nullptr) {
45
0
        *status = U_MEMORY_ALLOCATION_ERROR;
46
0
        return nullptr;
47
0
    }
48
    
49
4.76k
    newList->curr = nullptr;
50
4.76k
    newList->head = nullptr;
51
4.76k
    newList->tail = nullptr;
52
4.76k
    newList->size = 0;
53
    
54
4.76k
    return newList;
55
4.76k
}
56
57
/*
58
 * Function called by addItemEndList or addItemBeginList when the first item is added to the list.
59
 * This function properly sets the pointers for the first item added.
60
 */
61
4.76k
static void ulist_addFirstItem(UList *list, UListNode *newItem) {
62
4.76k
    newItem->next = nullptr;
63
4.76k
    newItem->previous = nullptr;
64
4.76k
    list->head = newItem;
65
4.76k
    list->tail = newItem;
66
4.76k
}
67
68
0
static void ulist_removeItem(UList *list, UListNode *p) {
69
0
    if (p->previous == nullptr) {
70
        // p is the list head.
71
0
        list->head = p->next;
72
0
    } else {
73
0
        p->previous->next = p->next;
74
0
    }
75
0
    if (p->next == nullptr) {
76
        // p is the list tail.
77
0
        list->tail = p->previous;
78
0
    } else {
79
0
        p->next->previous = p->previous;
80
0
    }
81
0
    if (p == list->curr) {
82
0
        list->curr = p->next;
83
0
    }
84
0
    --list->size;
85
0
    if (p->forceDelete) {
86
0
        uprv_free(p->data);
87
0
    }
88
0
    uprv_free(p);
89
0
}
90
91
85.8k
U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
92
85.8k
    UListNode *newItem = nullptr;
93
    
94
85.8k
    if (U_FAILURE(*status) || list == nullptr || data == nullptr) {
95
0
        if (forceDelete) {
96
0
            uprv_free((void *)data);
97
0
        }
98
0
        return;
99
0
    }
100
    
101
85.8k
    newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
102
85.8k
    if (newItem == nullptr) {
103
0
        if (forceDelete) {
104
0
            uprv_free((void *)data);
105
0
        }
106
0
        *status = U_MEMORY_ALLOCATION_ERROR;
107
0
        return;
108
0
    }
109
85.8k
    newItem->data = (void *)(data);
110
85.8k
    newItem->forceDelete = forceDelete;
111
    
112
85.8k
    if (list->size == 0) {
113
4.76k
        ulist_addFirstItem(list, newItem);
114
81.0k
    } else {
115
81.0k
        newItem->next = nullptr;
116
81.0k
        newItem->previous = list->tail;
117
81.0k
        list->tail->next = newItem;
118
81.0k
        list->tail = newItem;
119
81.0k
    }
120
    
121
85.8k
    list->size++;
122
85.8k
}
123
124
0
U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
125
0
    UListNode *newItem = nullptr;
126
    
127
0
    if (U_FAILURE(*status) || list == nullptr || data == nullptr) {
128
0
        if (forceDelete) {
129
0
            uprv_free((void *)data);
130
0
        }
131
0
        return;
132
0
    }
133
    
134
0
    newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
135
0
    if (newItem == nullptr) {
136
0
        if (forceDelete) {
137
0
            uprv_free((void *)data);
138
0
        }
139
0
        *status = U_MEMORY_ALLOCATION_ERROR;
140
0
        return;
141
0
    }
142
0
    newItem->data = (void *)(data);
143
0
    newItem->forceDelete = forceDelete;
144
    
145
0
    if (list->size == 0) {
146
0
        ulist_addFirstItem(list, newItem);
147
0
    } else {
148
0
        newItem->previous = nullptr;
149
0
        newItem->next = list->head;
150
0
        list->head->previous = newItem;
151
0
        list->head = newItem;
152
0
    }
153
    
154
0
    list->size++;
155
0
}
156
157
85.8k
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) {
158
85.8k
    if (list != nullptr) {
159
85.8k
        const UListNode *pointer;
160
815k
        for (pointer = list->head; pointer != nullptr; pointer = pointer->next) {
161
734k
            if (length == (int32_t)uprv_strlen((const char *)pointer->data)) {
162
66.7k
                if (uprv_memcmp(data, pointer->data, length) == 0) {
163
4.76k
                    return true;
164
4.76k
                }
165
66.7k
            }
166
734k
        }
167
85.8k
    }
168
81.0k
    return false;
169
85.8k
}
170
171
0
U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data) {
172
0
    if (list != nullptr) {
173
0
        UListNode *pointer;
174
0
        for (pointer = list->head; pointer != nullptr; pointer = pointer->next) {
175
0
            if (uprv_strcmp(data, (const char *)pointer->data) == 0) {
176
0
                ulist_removeItem(list, pointer);
177
                // Remove only the first occurrence, like Java LinkedList.remove(Object).
178
0
                return true;
179
0
            }
180
0
        }
181
0
    }
182
0
    return false;
183
0
}
184
185
38.8k
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
186
38.8k
    UListNode *curr = nullptr;
187
    
188
38.8k
    if (list == nullptr || list->curr == nullptr) {
189
0
        return nullptr;
190
0
    }
191
    
192
38.8k
    curr = list->curr;
193
38.8k
    list->curr = curr->next;
194
    
195
38.8k
    return curr->data;
196
38.8k
}
197
198
4.76k
U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) {
199
4.76k
    if (list != nullptr) {
200
4.76k
        return list->size;
201
4.76k
    }
202
    
203
0
    return -1;
204
4.76k
}
205
206
4.76k
U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
207
4.76k
    if (list != nullptr) {
208
4.76k
        list->curr = list->head;
209
4.76k
    }
210
4.76k
}
211
212
4.76k
U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) {
213
4.76k
    UListNode *listHead = nullptr;
214
215
4.76k
    if (list != nullptr) {
216
4.76k
        listHead = list->head;
217
90.5k
        while (listHead != nullptr) {
218
85.8k
            UListNode *listPointer = listHead->next;
219
220
85.8k
            if (listHead->forceDelete) {
221
4.76k
                uprv_free(listHead->data);
222
4.76k
            }
223
224
85.8k
            uprv_free(listHead);
225
85.8k
            listHead = listPointer;
226
85.8k
        }
227
4.76k
        uprv_free(list);
228
4.76k
        list = nullptr;
229
4.76k
    }
230
4.76k
}
231
232
4.76k
U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) {
233
4.76k
    if (en != nullptr) {
234
4.76k
        ulist_deleteList((UList *)(en->context));
235
4.76k
        uprv_free(en);
236
4.76k
    }
237
4.76k
}
238
239
4.76k
U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) {
240
4.76k
    if (U_FAILURE(*status)) {
241
0
        return -1;
242
0
    }
243
    
244
4.76k
    return ulist_getListSize((UList *)(en->context));
245
4.76k
}
246
247
38.8k
U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
248
38.8k
    const char *s;
249
38.8k
    if (U_FAILURE(*status)) {
250
0
        return nullptr;
251
0
    }
252
253
38.8k
    s = (const char *)ulist_getNext((UList *)(en->context));
254
38.8k
    if (s != nullptr && resultLength != nullptr) {
255
38.8k
        *resultLength = static_cast<int32_t>(uprv_strlen(s));
256
38.8k
    }
257
38.8k
    return s;
258
38.8k
}
259
260
0
U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration *en, UErrorCode *status) {
261
0
    if (U_FAILURE(*status)) {
262
0
        return ;
263
0
    }
264
    
265
0
    ulist_resetList((UList *)(en->context));
266
0
}
267
268
0
U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
269
0
    return (UList *)(en->context);
270
0
}