• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2 ******************************************************************************
3 *   Copyright (C) 2009-2014, International Business Machines
4 *   Corporation and others.  All Rights Reserved.
5 ******************************************************************************
6 */
7 
8 #include "ulist.h"
9 #include "cmemory.h"
10 #include "cstring.h"
11 #include "uenumimp.h"
12 
13 typedef struct UListNode UListNode;
14 struct UListNode {
15     void *data;
16 
17     UListNode *next;
18     UListNode *previous;
19 
20     /* When data is created with uprv_malloc, needs to be freed during deleteList function. */
21     UBool forceDelete;
22 };
23 
24 struct UList {
25     UListNode *curr;
26     UListNode *head;
27     UListNode *tail;
28 
29     int32_t size;
30     int32_t currentIndex;
31 };
32 
33 static void ulist_addFirstItem(UList *list, UListNode *newItem);
34 
ulist_createEmptyList(UErrorCode * status)35 U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) {
36     UList *newList = NULL;
37 
38     if (U_FAILURE(*status)) {
39         return NULL;
40     }
41 
42     newList = (UList *)uprv_malloc(sizeof(UList));
43     if (newList == NULL) {
44         *status = U_MEMORY_ALLOCATION_ERROR;
45         return NULL;
46     }
47 
48     newList->curr = NULL;
49     newList->head = NULL;
50     newList->tail = NULL;
51     newList->size = 0;
52     newList->currentIndex = -1;
53 
54     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  */
ulist_addFirstItem(UList * list,UListNode * newItem)61 static void ulist_addFirstItem(UList *list, UListNode *newItem) {
62     newItem->next = NULL;
63     newItem->previous = NULL;
64     list->head = newItem;
65     list->tail = newItem;
66     list->currentIndex = 0;
67 }
68 
ulist_addItemEndList(UList * list,const void * data,UBool forceDelete,UErrorCode * status)69 U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
70     UListNode *newItem = NULL;
71 
72     if (U_FAILURE(*status) || list == NULL || data == NULL) {
73         return;
74     }
75 
76     newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
77     if (newItem == NULL) {
78         *status = U_MEMORY_ALLOCATION_ERROR;
79         return;
80     }
81     newItem->data = (void *)(data);
82     newItem->forceDelete = forceDelete;
83 
84     if (list->size == 0) {
85         ulist_addFirstItem(list, newItem);
86     } else {
87         newItem->next = NULL;
88         newItem->previous = list->tail;
89         list->tail->next = newItem;
90         list->tail = newItem;
91     }
92 
93     list->size++;
94 }
95 
ulist_addItemBeginList(UList * list,const void * data,UBool forceDelete,UErrorCode * status)96 U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
97     UListNode *newItem = NULL;
98 
99     if (U_FAILURE(*status) || list == NULL || data == NULL) {
100         return;
101     }
102 
103     newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
104     if (newItem == NULL) {
105         *status = U_MEMORY_ALLOCATION_ERROR;
106         return;
107     }
108     newItem->data = (void *)(data);
109     newItem->forceDelete = forceDelete;
110 
111     if (list->size == 0) {
112         ulist_addFirstItem(list, newItem);
113     } else {
114         newItem->previous = NULL;
115         newItem->next = list->head;
116         list->head->previous = newItem;
117         list->head = newItem;
118         list->currentIndex++;
119     }
120 
121     list->size++;
122 }
123 
ulist_containsString(const UList * list,const char * data,int32_t length)124 U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) {
125     UBool result = FALSE;
126     const UListNode *pointer = NULL;
127 
128     if (list != NULL && list->size != 0) {
129         pointer = list->head;
130 
131         while (pointer != NULL) {
132             if (length == uprv_strlen(pointer->data)) {
133                 if (uprv_memcmp(data, pointer->data, length) == 0) {
134                     result = TRUE;
135                     break;
136                 }
137             }
138 
139             pointer = pointer->next;
140         }
141     }
142 
143     return result;
144 }
145 
ulist_getNext(UList * list)146 U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
147     UListNode *curr = NULL;
148 
149     if (list == NULL || list->curr == NULL) {
150         return NULL;
151     }
152 
153     curr = list->curr;
154     list->curr = curr->next;
155     list->currentIndex++;
156 
157     return curr->data;
158 }
159 
ulist_getListSize(const UList * list)160 U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) {
161     if (list != NULL) {
162         return list->size;
163     }
164 
165     return -1;
166 }
167 
ulist_resetList(UList * list)168 U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
169     if (list != NULL) {
170         list->curr = list->head;
171         list->currentIndex = 0;
172     }
173 }
174 
ulist_deleteList(UList * list)175 U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) {
176     UListNode *listHead = NULL;
177 
178     if (list != NULL) {
179         listHead = list->head;
180         while (listHead != NULL) {
181             UListNode *listPointer = listHead->next;
182 
183             if (listHead->forceDelete) {
184                 uprv_free(listHead->data);
185             }
186 
187             uprv_free(listHead);
188             listHead = listPointer;
189         }
190         uprv_free(list);
191         list = NULL;
192     }
193 }
194 
ulist_close_keyword_values_iterator(UEnumeration * en)195 U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) {
196     if (en != NULL) {
197         ulist_deleteList((UList *)(en->context));
198         uprv_free(en);
199     }
200 }
201 
ulist_count_keyword_values(UEnumeration * en,UErrorCode * status)202 U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) {
203     if (U_FAILURE(*status)) {
204         return -1;
205     }
206 
207     return ulist_getListSize((UList *)(en->context));
208 }
209 
ulist_next_keyword_value(UEnumeration * en,int32_t * resultLength,UErrorCode * status)210 U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
211     const char *s;
212     if (U_FAILURE(*status)) {
213         return NULL;
214     }
215 
216     s = (const char *)ulist_getNext((UList *)(en->context));
217     if (s != NULL && resultLength != NULL) {
218         *resultLength = uprv_strlen(s);
219     }
220     return s;
221 }
222 
ulist_reset_keyword_values_iterator(UEnumeration * en,UErrorCode * status)223 U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration *en, UErrorCode *status) {
224     if (U_FAILURE(*status)) {
225         return ;
226     }
227 
228     ulist_resetList((UList *)(en->context));
229 }
230 
ulist_getListFromEnum(UEnumeration * en)231 U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
232     return (UList *)(en->context);
233 }
234 
235