Line data Source code
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 : }
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 : }
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 : }
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 : } else {
73 0 : p->previous->next = p->next;
74 : }
75 0 : if (p->next == NULL) {
76 : // p is the list tail.
77 0 : list->tail = p->previous;
78 : } else {
79 0 : p->next->previous = p->previous;
80 : }
81 0 : if (p == list->curr) {
82 0 : list->curr = p->next;
83 : }
84 0 : --list->size;
85 0 : if (p->forceDelete) {
86 0 : uprv_free(p->data);
87 : }
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 : }
98 0 : return;
99 : }
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 : }
106 0 : *status = U_MEMORY_ALLOCATION_ERROR;
107 0 : return;
108 : }
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 : } else {
115 0 : newItem->next = NULL;
116 0 : newItem->previous = list->tail;
117 0 : list->tail->next = newItem;
118 0 : list->tail = newItem;
119 : }
120 :
121 0 : list->size++;
122 : }
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 : }
131 0 : return;
132 : }
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 : }
139 0 : *status = U_MEMORY_ALLOCATION_ERROR;
140 0 : return;
141 : }
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 : } else {
148 0 : newItem->previous = NULL;
149 0 : newItem->next = list->head;
150 0 : list->head->previous = newItem;
151 0 : list->head = newItem;
152 : }
153 :
154 0 : list->size++;
155 : }
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 : 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 : }
165 : }
166 : }
167 : }
168 0 : return FALSE;
169 : }
170 :
171 0 : U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data) {
172 0 : if (list != NULL) {
173 : 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 : }
180 : }
181 : }
182 0 : return FALSE;
183 : }
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 : }
191 :
192 0 : curr = list->curr;
193 0 : list->curr = curr->next;
194 :
195 0 : return curr->data;
196 : }
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 : }
202 :
203 0 : return -1;
204 : }
205 :
206 0 : U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
207 0 : if (list != NULL) {
208 0 : list->curr = list->head;
209 : }
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 : }
223 :
224 0 : uprv_free(listHead);
225 0 : listHead = listPointer;
226 : }
227 0 : uprv_free(list);
228 0 : list = NULL;
229 : }
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 : }
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 : }
243 :
244 0 : return ulist_getListSize((UList *)(en->context));
245 : }
246 :
247 0 : U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
248 : const char *s;
249 0 : if (U_FAILURE(*status)) {
250 0 : return NULL;
251 : }
252 :
253 0 : s = (const char *)ulist_getNext((UList *)(en->context));
254 0 : if (s != NULL && resultLength != NULL) {
255 0 : *resultLength = uprv_strlen(s);
256 : }
257 0 : return s;
258 : }
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 : }
264 :
265 0 : ulist_resetList((UList *)(en->context));
266 : }
267 :
268 0 : U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
269 0 : return (UList *)(en->context);
270 : }
|