Home | History | Annotate | Download | only in common
      1 // Copyright (C) 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     int32_t currentIndex;
     33 };
     34 
     35 static void ulist_addFirstItem(UList *list, UListNode *newItem);
     36 
     37 U_CAPI UList *U_EXPORT2 ulist_createEmptyList(UErrorCode *status) {
     38     UList *newList = NULL;
     39 
     40     if (U_FAILURE(*status)) {
     41         return NULL;
     42     }
     43 
     44     newList = (UList *)uprv_malloc(sizeof(UList));
     45     if (newList == NULL) {
     46         *status = U_MEMORY_ALLOCATION_ERROR;
     47         return NULL;
     48     }
     49 
     50     newList->curr = NULL;
     51     newList->head = NULL;
     52     newList->tail = NULL;
     53     newList->size = 0;
     54     newList->currentIndex = -1;
     55 
     56     return newList;
     57 }
     58 
     59 /*
     60  * Function called by addItemEndList or addItemBeginList when the first item is added to the list.
     61  * This function properly sets the pointers for the first item added.
     62  */
     63 static void ulist_addFirstItem(UList *list, UListNode *newItem) {
     64     newItem->next = NULL;
     65     newItem->previous = NULL;
     66     list->head = newItem;
     67     list->tail = newItem;
     68 }
     69 
     70 static void ulist_removeItem(UList *list, UListNode *p) {
     71     if (p->previous == NULL) {
     72         // p is the list head.
     73         list->head = p->next;
     74     } else {
     75         p->previous->next = p->next;
     76     }
     77     if (p->next == NULL) {
     78         // p is the list tail.
     79         list->tail = p->previous;
     80     } else {
     81         p->next->previous = p->previous;
     82     }
     83     list->curr = NULL;
     84     list->currentIndex = 0;
     85     --list->size;
     86     if (p->forceDelete) {
     87         uprv_free(p->data);
     88     }
     89     uprv_free(p);
     90 }
     91 
     92 U_CAPI void U_EXPORT2 ulist_addItemEndList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
     93     UListNode *newItem = NULL;
     94 
     95     if (U_FAILURE(*status) || list == NULL || data == NULL) {
     96         if (forceDelete) {
     97             uprv_free((void *)data);
     98         }
     99         return;
    100     }
    101 
    102     newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
    103     if (newItem == NULL) {
    104         if (forceDelete) {
    105             uprv_free((void *)data);
    106         }
    107         *status = U_MEMORY_ALLOCATION_ERROR;
    108         return;
    109     }
    110     newItem->data = (void *)(data);
    111     newItem->forceDelete = forceDelete;
    112 
    113     if (list->size == 0) {
    114         ulist_addFirstItem(list, newItem);
    115     } else {
    116         newItem->next = NULL;
    117         newItem->previous = list->tail;
    118         list->tail->next = newItem;
    119         list->tail = newItem;
    120     }
    121 
    122     list->size++;
    123 }
    124 
    125 U_CAPI void U_EXPORT2 ulist_addItemBeginList(UList *list, const void *data, UBool forceDelete, UErrorCode *status) {
    126     UListNode *newItem = NULL;
    127 
    128     if (U_FAILURE(*status) || list == NULL || data == NULL) {
    129         if (forceDelete) {
    130             uprv_free((void *)data);
    131         }
    132         return;
    133     }
    134 
    135     newItem = (UListNode *)uprv_malloc(sizeof(UListNode));
    136     if (newItem == NULL) {
    137         if (forceDelete) {
    138             uprv_free((void *)data);
    139         }
    140         *status = U_MEMORY_ALLOCATION_ERROR;
    141         return;
    142     }
    143     newItem->data = (void *)(data);
    144     newItem->forceDelete = forceDelete;
    145 
    146     if (list->size == 0) {
    147         ulist_addFirstItem(list, newItem);
    148     } else {
    149         newItem->previous = NULL;
    150         newItem->next = list->head;
    151         list->head->previous = newItem;
    152         list->head = newItem;
    153         list->currentIndex++;
    154     }
    155 
    156     list->size++;
    157 }
    158 
    159 U_CAPI UBool U_EXPORT2 ulist_containsString(const UList *list, const char *data, int32_t length) {
    160     if (list != NULL) {
    161         const UListNode *pointer;
    162         for (pointer = list->head; pointer != NULL; pointer = pointer->next) {
    163             if (length == uprv_strlen(pointer->data)) {
    164                 if (uprv_memcmp(data, pointer->data, length) == 0) {
    165                     return TRUE;
    166                 }
    167             }
    168         }
    169     }
    170     return FALSE;
    171 }
    172 
    173 U_CAPI UBool U_EXPORT2 ulist_removeString(UList *list, const char *data) {
    174     if (list != NULL) {
    175         UListNode *pointer;
    176         for (pointer = list->head; pointer != NULL; pointer = pointer->next) {
    177             if (uprv_strcmp(data, pointer->data) == 0) {
    178                 ulist_removeItem(list, pointer);
    179                 // Remove only the first occurrence, like Java LinkedList.remove(Object).
    180                 return TRUE;
    181             }
    182         }
    183     }
    184     return FALSE;
    185 }
    186 
    187 U_CAPI void *U_EXPORT2 ulist_getNext(UList *list) {
    188     UListNode *curr = NULL;
    189 
    190     if (list == NULL || list->curr == NULL) {
    191         return NULL;
    192     }
    193 
    194     curr = list->curr;
    195     list->curr = curr->next;
    196     list->currentIndex++;
    197 
    198     return curr->data;
    199 }
    200 
    201 U_CAPI int32_t U_EXPORT2 ulist_getListSize(const UList *list) {
    202     if (list != NULL) {
    203         return list->size;
    204     }
    205 
    206     return -1;
    207 }
    208 
    209 U_CAPI void U_EXPORT2 ulist_resetList(UList *list) {
    210     if (list != NULL) {
    211         list->curr = list->head;
    212         list->currentIndex = 0;
    213     }
    214 }
    215 
    216 U_CAPI void U_EXPORT2 ulist_deleteList(UList *list) {
    217     UListNode *listHead = NULL;
    218 
    219     if (list != NULL) {
    220         listHead = list->head;
    221         while (listHead != NULL) {
    222             UListNode *listPointer = listHead->next;
    223 
    224             if (listHead->forceDelete) {
    225                 uprv_free(listHead->data);
    226             }
    227 
    228             uprv_free(listHead);
    229             listHead = listPointer;
    230         }
    231         uprv_free(list);
    232         list = NULL;
    233     }
    234 }
    235 
    236 U_CAPI void U_EXPORT2 ulist_close_keyword_values_iterator(UEnumeration *en) {
    237     if (en != NULL) {
    238         ulist_deleteList((UList *)(en->context));
    239         uprv_free(en);
    240     }
    241 }
    242 
    243 U_CAPI int32_t U_EXPORT2 ulist_count_keyword_values(UEnumeration *en, UErrorCode *status) {
    244     if (U_FAILURE(*status)) {
    245         return -1;
    246     }
    247 
    248     return ulist_getListSize((UList *)(en->context));
    249 }
    250 
    251 U_CAPI const char * U_EXPORT2 ulist_next_keyword_value(UEnumeration *en, int32_t *resultLength, UErrorCode *status) {
    252     const char *s;
    253     if (U_FAILURE(*status)) {
    254         return NULL;
    255     }
    256 
    257     s = (const char *)ulist_getNext((UList *)(en->context));
    258     if (s != NULL && resultLength != NULL) {
    259         *resultLength = uprv_strlen(s);
    260     }
    261     return s;
    262 }
    263 
    264 U_CAPI void U_EXPORT2 ulist_reset_keyword_values_iterator(UEnumeration *en, UErrorCode *status) {
    265     if (U_FAILURE(*status)) {
    266         return ;
    267     }
    268 
    269     ulist_resetList((UList *)(en->context));
    270 }
    271 
    272 U_CAPI UList * U_EXPORT2 ulist_getListFromEnum(UEnumeration *en) {
    273     return (UList *)(en->context);
    274 }
    275 
    276