1 // © 2016 and later: Unicode, Inc. and others.
2 // License & terms of use: http://www.unicode.org/copyright.html
4 ******************************************************************************
5 * Copyright (C) 2009-2016, International Business Machines
6 * Corporation and others. All Rights Reserved.
7 ******************************************************************************
15 typedef struct UListNode UListNode
;
22 /* When data is created with uprv_malloc, needs to be freed during deleteList function. */
34 static void ulist_addFirstItem(UList
*list
, UListNode
*newItem
);
36 U_CAPI UList
*U_EXPORT2
ulist_createEmptyList(UErrorCode
*status
) {
37 UList
*newList
= NULL
;
39 if (U_FAILURE(*status
)) {
43 newList
= (UList
*)uprv_malloc(sizeof(UList
));
44 if (newList
== NULL
) {
45 *status
= U_MEMORY_ALLOCATION_ERROR
;
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.
61 static void ulist_addFirstItem(UList
*list
, UListNode
*newItem
) {
63 newItem
->previous
= NULL
;
68 static void ulist_removeItem(UList
*list
, UListNode
*p
) {
69 if (p
->previous
== NULL
) {
70 // p is the list head.
73 p
->previous
->next
= p
->next
;
75 if (p
->next
== NULL
) {
76 // p is the list tail.
77 list
->tail
= p
->previous
;
79 p
->next
->previous
= p
->previous
;
81 if (p
== list
->curr
) {
91 U_CAPI
void U_EXPORT2
ulist_addItemEndList(UList
*list
, const void *data
, UBool forceDelete
, UErrorCode
*status
) {
92 UListNode
*newItem
= NULL
;
94 if (U_FAILURE(*status
) || list
== NULL
|| data
== NULL
) {
96 uprv_free((void *)data
);
101 newItem
= (UListNode
*)uprv_malloc(sizeof(UListNode
));
102 if (newItem
== NULL
) {
104 uprv_free((void *)data
);
106 *status
= U_MEMORY_ALLOCATION_ERROR
;
109 newItem
->data
= (void *)(data
);
110 newItem
->forceDelete
= forceDelete
;
112 if (list
->size
== 0) {
113 ulist_addFirstItem(list
, newItem
);
115 newItem
->next
= NULL
;
116 newItem
->previous
= list
->tail
;
117 list
->tail
->next
= newItem
;
118 list
->tail
= newItem
;
124 U_CAPI
void U_EXPORT2
ulist_addItemBeginList(UList
*list
, const void *data
, UBool forceDelete
, UErrorCode
*status
) {
125 UListNode
*newItem
= NULL
;
127 if (U_FAILURE(*status
) || list
== NULL
|| data
== NULL
) {
129 uprv_free((void *)data
);
134 newItem
= (UListNode
*)uprv_malloc(sizeof(UListNode
));
135 if (newItem
== NULL
) {
137 uprv_free((void *)data
);
139 *status
= U_MEMORY_ALLOCATION_ERROR
;
142 newItem
->data
= (void *)(data
);
143 newItem
->forceDelete
= forceDelete
;
145 if (list
->size
== 0) {
146 ulist_addFirstItem(list
, newItem
);
148 newItem
->previous
= NULL
;
149 newItem
->next
= list
->head
;
150 list
->head
->previous
= newItem
;
151 list
->head
= newItem
;
157 U_CAPI UBool U_EXPORT2
ulist_containsString(const UList
*list
, const char *data
, int32_t length
) {
159 const UListNode
*pointer
;
160 for (pointer
= list
->head
; pointer
!= NULL
; pointer
= pointer
->next
) {
161 if (length
== (int32_t)uprv_strlen((const char *)pointer
->data
)) {
162 if (uprv_memcmp(data
, pointer
->data
, length
) == 0) {
171 U_CAPI UBool U_EXPORT2
ulist_removeString(UList
*list
, const char *data
) {
174 for (pointer
= list
->head
; pointer
!= NULL
; pointer
= pointer
->next
) {
175 if (uprv_strcmp(data
, (const char *)pointer
->data
) == 0) {
176 ulist_removeItem(list
, pointer
);
177 // Remove only the first occurrence, like Java LinkedList.remove(Object).
185 U_CAPI
void *U_EXPORT2
ulist_getNext(UList
*list
) {
186 UListNode
*curr
= NULL
;
188 if (list
== NULL
|| list
->curr
== NULL
) {
193 list
->curr
= curr
->next
;
198 U_CAPI
int32_t U_EXPORT2
ulist_getListSize(const UList
*list
) {
206 U_CAPI
void U_EXPORT2
ulist_resetList(UList
*list
) {
208 list
->curr
= list
->head
;
212 U_CAPI
void U_EXPORT2
ulist_deleteList(UList
*list
) {
213 UListNode
*listHead
= NULL
;
216 listHead
= list
->head
;
217 while (listHead
!= NULL
) {
218 UListNode
*listPointer
= listHead
->next
;
220 if (listHead
->forceDelete
) {
221 uprv_free(listHead
->data
);
225 listHead
= listPointer
;
232 U_CAPI
void U_EXPORT2
ulist_close_keyword_values_iterator(UEnumeration
*en
) {
234 ulist_deleteList((UList
*)(en
->context
));
239 U_CAPI
int32_t U_EXPORT2
ulist_count_keyword_values(UEnumeration
*en
, UErrorCode
*status
) {
240 if (U_FAILURE(*status
)) {
244 return ulist_getListSize((UList
*)(en
->context
));
247 U_CAPI
const char * U_EXPORT2
ulist_next_keyword_value(UEnumeration
*en
, int32_t *resultLength
, UErrorCode
*status
) {
249 if (U_FAILURE(*status
)) {
253 s
= (const char *)ulist_getNext((UList
*)(en
->context
));
254 if (s
!= NULL
&& resultLength
!= NULL
) {
255 *resultLength
= uprv_strlen(s
);
260 U_CAPI
void U_EXPORT2
ulist_reset_keyword_values_iterator(UEnumeration
*en
, UErrorCode
*status
) {
261 if (U_FAILURE(*status
)) {
265 ulist_resetList((UList
*)(en
->context
));
268 U_CAPI UList
* U_EXPORT2
ulist_getListFromEnum(UEnumeration
*en
) {
269 return (UList
*)(en
->context
);