tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ulist.cpp (7121B)


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