Home | History | Annotate | Download | only in common
      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 
     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  */
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    231 U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
    232     return (UList *)(en->context);
    233 }
    234 
    235