michael@0: /* michael@0: ****************************************************************************** michael@0: * Copyright (C) 2009-2012, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ****************************************************************************** michael@0: */ michael@0: michael@0: #include "ulist.h" michael@0: #include "cmemory.h" michael@0: #include "cstring.h" michael@0: #include "uenumimp.h" michael@0: michael@0: typedef struct UListNode UListNode; michael@0: struct UListNode { michael@0: void *data; michael@0: michael@0: UListNode *next; michael@0: UListNode *previous; michael@0: michael@0: /* When data is created with uprv_malloc, needs to be freed during deleteList function. */ michael@0: UBool forceDelete; michael@0: }; michael@0: michael@0: struct UList { michael@0: UListNode *curr; michael@0: UListNode *head; michael@0: UListNode *tail; michael@0: michael@0: int32_t size; michael@0: int32_t currentIndex; michael@0: }; michael@0: michael@0: static void ulist_addFirstItem(UList *list, UListNode *newItem); michael@0: michael@0: U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) { michael@0: UList *newList = NULL; michael@0: michael@0: if (U_FAILURE(*status)) { michael@0: return NULL; michael@0: } michael@0: michael@0: newList = (UList *)uprv_malloc(sizeof(UList)); michael@0: if (newList == NULL) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return NULL; michael@0: } michael@0: michael@0: newList->curr = NULL; michael@0: newList->head = NULL; michael@0: newList->tail = NULL; michael@0: newList->size = 0; michael@0: newList->currentIndex = -1; michael@0: michael@0: return newList; michael@0: } michael@0: michael@0: /* michael@0: * Function called by addItemEndList or addItemBeginList when the first item is added to the list. michael@0: * This function properly sets the pointers for the first item added. michael@0: */ michael@0: static void ulist_addFirstItem(UList *list, UListNode *newItem) { michael@0: newItem->next = NULL; michael@0: newItem->previous = NULL; michael@0: list->head = newItem; michael@0: list->tail = newItem; michael@0: list->currentIndex = 0; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) { michael@0: UListNode *newItem = NULL; michael@0: michael@0: if (U_FAILURE(*status) || list == NULL || data == NULL) { michael@0: return; michael@0: } michael@0: michael@0: newItem = (UListNode *)uprv_malloc(sizeof(UListNode)); michael@0: if (newItem == NULL) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return; michael@0: } michael@0: newItem->data = (void *)(data); michael@0: newItem->forceDelete = forceDelete; michael@0: michael@0: if (list->size == 0) { michael@0: ulist_addFirstItem(list, newItem); michael@0: } else { michael@0: newItem->next = NULL; michael@0: newItem->previous = list->tail; michael@0: list->tail->next = newItem; michael@0: list->tail = newItem; michael@0: } michael@0: michael@0: list->size++; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) { michael@0: UListNode *newItem = NULL; michael@0: michael@0: if (U_FAILURE(*status) || list == NULL || data == NULL) { michael@0: return; michael@0: } michael@0: michael@0: newItem = (UListNode *)uprv_malloc(sizeof(UListNode)); michael@0: if (newItem == NULL) { michael@0: *status = U_MEMORY_ALLOCATION_ERROR; michael@0: return; michael@0: } michael@0: newItem->data = (void *)(data); michael@0: newItem->forceDelete = forceDelete; michael@0: michael@0: if (list->size == 0) { michael@0: ulist_addFirstItem(list, newItem); michael@0: } else { michael@0: newItem->previous = NULL; michael@0: newItem->next = list->head; michael@0: list->head->previous = newItem; michael@0: list->head = newItem; michael@0: list->currentIndex++; michael@0: } michael@0: michael@0: list->size++; michael@0: } michael@0: michael@0: U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) { michael@0: UBool result = FALSE; michael@0: const UListNode *pointer = NULL; michael@0: michael@0: if (list != NULL && list->size != 0) { michael@0: pointer = list->head; michael@0: michael@0: while (pointer != NULL) { michael@0: if (length == uprv_strlen(pointer->data)) { michael@0: if (uprv_memcmp(data, pointer->data, length) == 0) { michael@0: result = TRUE; michael@0: break; michael@0: } michael@0: } michael@0: michael@0: pointer = pointer->next; michael@0: } michael@0: } michael@0: michael@0: return result; michael@0: } michael@0: michael@0: U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) { michael@0: UListNode *curr = NULL; michael@0: michael@0: if (list == NULL || list->curr == NULL) { michael@0: return NULL; michael@0: } michael@0: michael@0: curr = list->curr; michael@0: list->curr = curr->next; michael@0: list->currentIndex++; michael@0: michael@0: return curr->data; michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) { michael@0: if (list != NULL) { michael@0: return list->size; michael@0: } michael@0: michael@0: return -1; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_resetList(UList *list) { michael@0: if (list != NULL) { michael@0: list->curr = list->head; michael@0: list->currentIndex = 0; michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) { michael@0: UListNode *listHead = NULL; michael@0: UListNode *listPointer = NULL; michael@0: michael@0: if (list != NULL) { michael@0: listHead = list->head; michael@0: listPointer = listHead; michael@0: while (listHead != NULL) { michael@0: listPointer = listHead->next; michael@0: michael@0: if (listHead->forceDelete) { michael@0: uprv_free(listHead->data); michael@0: } michael@0: michael@0: uprv_free(listHead); michael@0: listHead = listPointer; michael@0: } michael@0: uprv_free(list); michael@0: list = NULL; michael@0: } michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) { michael@0: if (en != NULL) { michael@0: ulist_deleteList((UList *)(en->context)); michael@0: uprv_free(en); michael@0: } michael@0: } michael@0: michael@0: U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) { michael@0: if (U_FAILURE(*status)) { michael@0: return -1; michael@0: } michael@0: michael@0: return ulist_getListSize((UList *)(en->context)); michael@0: } michael@0: michael@0: U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) { michael@0: const char *s; michael@0: if (U_FAILURE(*status)) { michael@0: return NULL; michael@0: } michael@0: michael@0: s = (const char *)ulist_getNext((UList *)(en->context)); michael@0: if (s != NULL && resultLength != NULL) { michael@0: *resultLength = uprv_strlen(s); michael@0: } michael@0: return s; michael@0: } michael@0: michael@0: U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration *en, UErrorCode *status) { michael@0: if (U_FAILURE(*status)) { michael@0: return ; michael@0: } michael@0: michael@0: ulist_resetList((UList *)(en->context)); michael@0: } michael@0: michael@0: U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) { michael@0: return (UList *)(en->context); michael@0: } michael@0: