Coverage Report

Created: 2025-06-24 06:43

/src/icu/source/common/ulist.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) 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
0
U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) {
37
0
    UList *newList = NULL;
38
    
39
0
    if (U_FAILURE(*status)) {
40
0
        return NULL;
41
0
    }
42
    
43
0
    newList = (UList *)uprv_malloc(sizeof(UList));
44
0
    if (newList == NULL) {
45
0
        *status = U_MEMORY_ALLOCATION_ERROR;
46
0
        return NULL;
47
0
    }
48
    
49
0
    newList->curr = NULL;
50
0
    newList->head = NULL;
51
0
    newList->tail = NULL;
52
0
    newList->size = 0;
53
    
54
0
    return newList;
55
0
}
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
0
static void ulist_addFirstItem(UList *list, UListNode *newItem) {
62
0
    newItem->next = NULL;
63
0
    newItem->previous = NULL;
64
0
    list->head = newItem;
65
0
    list->tail = newItem;
66
0
}
67
68
0
static void ulist_removeItem(UList *list, UListNode *p) {
69
0
    if (p->previous == NULL) {
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 == NULL) {
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
0
U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
92
0
    UListNode *newItem = NULL;
93
    
94
0
    if (U_FAILURE(*status) || list == NULL || data == NULL) {
95
0
        if (forceDelete) {
96
0
            uprv_free((void *)data);
97
0
        }
98
0
        return;
99
0
    }
100
    
101
0
    newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
102
0
    if (newItem == NULL) {
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
0
    newItem->data = (void *)(data);
110
0
    newItem->forceDelete = forceDelete;
111
    
112
0
    if (list->size == 0) {
113
0
        ulist_addFirstItem(list, newItem);
114
0
    } else {
115
0
        newItem->next = NULL;
116
0
        newItem->previous = list->tail;
117
0
        list->tail->next = newItem;
118
0
        list->tail = newItem;
119
0
    }
120
    
121
0
    list->size++;
122
0
}
123
124
0
U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
125
0
    UListNode *newItem = NULL;
126
    
127
0
    if (U_FAILURE(*status) || list == NULL || data == NULL) {
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 == NULL) {
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 = NULL;
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
0
U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) {
158
0
    if (list != NULL) {
159
0
        const UListNode *pointer;
160
0
        for (pointer = list->head; pointer != NULL; pointer = pointer->next) {
161
0
            if (length == (int32_t)uprv_strlen((const char *)pointer->data)) {
162
0
                if (uprv_memcmp(data, pointer->data, length) == 0) {
163
0
                    return TRUE;
164
0
                }
165
0
            }
166
0
        }
167
0
    }
168
0
    return FALSE;
169
0
}
170
171
0
U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data) {
172
0
    if (list != NULL) {
173
0
        UListNode *pointer;
174
0
        for (pointer = list->head; pointer != NULL; 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
0
U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
186
0
    UListNode *curr = NULL;
187
    
188
0
    if (list == NULL || list->curr == NULL) {
189
0
        return NULL;
190
0
    }
191
    
192
0
    curr = list->curr;
193
0
    list->curr = curr->next;
194
    
195
0
    return curr->data;
196
0
}
197
198
0
U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) {
199
0
    if (list != NULL) {
200
0
        return list->size;
201
0
    }
202
    
203
0
    return -1;
204
0
}
205
206
0
U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
207
0
    if (list != NULL) {
208
0
        list->curr = list->head;
209
0
    }
210
0
}
211
212
0
U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) {
213
0
    UListNode *listHead = NULL;
214
215
0
    if (list != NULL) {
216
0
        listHead = list->head;
217
0
        while (listHead != NULL) {
218
0
            UListNode *listPointer = listHead->next;
219
220
0
            if (listHead->forceDelete) {
221
0
                uprv_free(listHead->data);
222
0
            }
223
224
0
            uprv_free(listHead);
225
0
            listHead = listPointer;
226
0
        }
227
0
        uprv_free(list);
228
0
        list = NULL;
229
0
    }
230
0
}
231
232
0
U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) {
233
0
    if (en != NULL) {
234
0
        ulist_deleteList((UList *)(en->context));
235
0
        uprv_free(en);
236
0
    }
237
0
}
238
239
0
U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) {
240
0
    if (U_FAILURE(*status)) {
241
0
        return -1;
242
0
    }
243
    
244
0
    return ulist_getListSize((UList *)(en->context));
245
0
}
246
247
0
U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
248
0
    const char *s;
249
0
    if (U_FAILURE(*status)) {
250
0
        return NULL;
251
0
    }
252
253
0
    s = (const char *)ulist_getNext((UList *)(en->context));
254
0
    if (s != NULL && resultLength != NULL) {
255
0
        *resultLength = static_cast<int32_t>(uprv_strlen(s));
256
0
    }
257
0
    return s;
258
0
}
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
}