tor-browser

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

uvector.cpp (17193B)


      1 // © 2016 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 /*
      4 ******************************************************************************
      5 * Copyright (C) 1999-2013, International Business Machines Corporation and
      6 * others. All Rights Reserved.
      7 ******************************************************************************
      8 *   Date        Name        Description
      9 *   10/22/99    alan        Creation.
     10 **********************************************************************
     11 */
     12 
     13 #include "uvector.h"
     14 #include "cmemory.h"
     15 #include "uarrsort.h"
     16 #include "uelement.h"
     17 
     18 U_NAMESPACE_BEGIN
     19 
     20 constexpr int32_t DEFAULT_CAPACITY = 8;
     21 
     22 /*
     23 * Constants for hinting whether a key is an integer
     24 * or a pointer.  If a hint bit is zero, then the associated
     25 * token is assumed to be an integer. This is needed for iSeries
     26 */
     27 constexpr int8_t HINT_KEY_POINTER = 1;
     28 constexpr int8_t HINT_KEY_INTEGER = 0;
     29 
     30 UOBJECT_DEFINE_RTTI_IMPLEMENTATION(UVector)
     31 
     32 UVector::UVector(UErrorCode &status) :
     33        UVector(nullptr, nullptr, DEFAULT_CAPACITY, status) {
     34 }
     35 
     36 UVector::UVector(int32_t initialCapacity, UErrorCode &status) :
     37        UVector(nullptr, nullptr, initialCapacity, status) {
     38 }
     39 
     40 UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status) :
     41        UVector(d, c, DEFAULT_CAPACITY, status) {
     42 }
     43 
     44 UVector::UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status) :
     45    deleter(d),
     46    comparer(c)
     47 {
     48    if (U_FAILURE(status)) {
     49        return;
     50    }
     51    // Fix bogus initialCapacity values; avoid malloc(0) and integer overflow
     52    if ((initialCapacity < 1) || (initialCapacity > static_cast<int32_t>(INT32_MAX / sizeof(UElement)))) {
     53        initialCapacity = DEFAULT_CAPACITY;
     54    }
     55    elements = static_cast<UElement*>(uprv_malloc(sizeof(UElement) * initialCapacity));
     56    if (elements == nullptr) {
     57        status = U_MEMORY_ALLOCATION_ERROR;
     58    } else {
     59        capacity = initialCapacity;
     60    }
     61 }
     62 
     63 UVector::~UVector() {
     64    removeAllElements();
     65    uprv_free(elements);
     66    elements = nullptr;
     67 }
     68 
     69 /**
     70 * Assign this object to another (make this a copy of 'other').
     71 * Use the 'assign' function to assign each element.
     72 */
     73 void UVector::assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec) {
     74    if (ensureCapacity(other.count, ec)) {
     75        setSize(other.count, ec);
     76        if (U_SUCCESS(ec)) {
     77            for (int32_t i=0; i<other.count; ++i) {
     78                if (elements[i].pointer != nullptr && deleter != nullptr) {
     79                    (*deleter)(elements[i].pointer);
     80                }
     81                (*assign)(&elements[i], &other.elements[i]);
     82            }
     83        }
     84    }
     85 }
     86 
     87 // This only does something sensible if this object has a non-null comparer
     88 bool UVector::operator==(const UVector& other) const {
     89    U_ASSERT(comparer != nullptr);
     90    if (count != other.count) return false;
     91    if (comparer != nullptr) {
     92        // Compare using this object's comparer
     93        for (int32_t i=0; i<count; ++i) {
     94            if (!(*comparer)(elements[i], other.elements[i])) {
     95                return false;
     96            }
     97        }
     98    }
     99    return true;
    100 }
    101 
    102 void UVector::addElement(void* obj, UErrorCode &status) {
    103    U_ASSERT(deleter == nullptr);
    104    if (ensureCapacity(count + 1, status)) {
    105        elements[count++].pointer = obj;
    106    }
    107 }
    108 
    109 void UVector::adoptElement(void* obj, UErrorCode &status) {
    110    U_ASSERT(deleter != nullptr);
    111    if (ensureCapacity(count + 1, status)) {
    112        elements[count++].pointer = obj;
    113    } else {
    114        (*deleter)(obj);
    115    }
    116 }
    117 void UVector::addElement(int32_t elem, UErrorCode &status) {
    118    U_ASSERT(deleter == nullptr);  // Usage error. Mixing up ints and pointers.
    119    if (ensureCapacity(count + 1, status)) {
    120        elements[count].pointer = nullptr;     // Pointers may be bigger than ints.
    121        elements[count].integer = elem;
    122        count++;
    123    }
    124 }
    125 
    126 void UVector::setElementAt(void* obj, int32_t index) {
    127    if (0 <= index && index < count) {
    128        if (elements[index].pointer != nullptr && deleter != nullptr) {
    129            (*deleter)(elements[index].pointer);
    130        }
    131        elements[index].pointer = obj;
    132    } else {
    133        /* index out of range */
    134        if (deleter != nullptr) {
    135            (*deleter)(obj);
    136        }
    137    }
    138 }
    139 
    140 void UVector::setElementAt(int32_t elem, int32_t index) {
    141    U_ASSERT(deleter == nullptr);  // Usage error. Mixing up ints and pointers.
    142    if (0 <= index && index < count) {
    143        elements[index].pointer = nullptr;
    144        elements[index].integer = elem;
    145    }
    146    /* else index out of range */
    147 }
    148 
    149 void UVector::insertElementAt(void* obj, int32_t index, UErrorCode &status) {
    150    if (ensureCapacity(count + 1, status)) {
    151        if (0 <= index && index <= count) {
    152            for (int32_t i=count; i>index; --i) {
    153                elements[i] = elements[i-1];
    154            }
    155            elements[index].pointer = obj;
    156            ++count;
    157        } else {
    158            /* index out of range */
    159            status = U_ILLEGAL_ARGUMENT_ERROR;
    160        }
    161    }
    162    if (U_FAILURE(status) && deleter != nullptr) {
    163        (*deleter)(obj);
    164    }
    165 }
    166 
    167 void UVector::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
    168    U_ASSERT(deleter == nullptr);  // Usage error. Mixing up ints and pointers.
    169    // must have 0 <= index <= count
    170    if (ensureCapacity(count + 1, status)) {
    171        if (0 <= index && index <= count) {
    172            for (int32_t i=count; i>index; --i) {
    173                elements[i] = elements[i-1];
    174            }
    175            elements[index].pointer = nullptr;
    176            elements[index].integer = elem;
    177            ++count;
    178        } else {
    179            /* index out of range */
    180            status = U_ILLEGAL_ARGUMENT_ERROR;
    181        }
    182    }
    183 }
    184 
    185 void* UVector::elementAt(int32_t index) const {
    186    return (0 <= index && index < count) ? elements[index].pointer : nullptr;
    187 }
    188 
    189 int32_t UVector::elementAti(int32_t index) const {
    190    return (0 <= index && index < count) ? elements[index].integer : 0;
    191 }
    192 
    193 UBool UVector::containsAll(const UVector& other) const {
    194    for (int32_t i=0; i<other.size(); ++i) {
    195        if (indexOf(other.elements[i]) < 0) {
    196            return false;
    197        }
    198    }
    199    return true;
    200 }
    201 
    202 UBool UVector::containsNone(const UVector& other) const {
    203    for (int32_t i=0; i<other.size(); ++i) {
    204        if (indexOf(other.elements[i]) >= 0) {
    205            return false;
    206        }
    207    }
    208    return true;
    209 }
    210 
    211 UBool UVector::removeAll(const UVector& other) {
    212    UBool changed = false;
    213    for (int32_t i=0; i<other.size(); ++i) {
    214        int32_t j = indexOf(other.elements[i]);
    215        if (j >= 0) {
    216            removeElementAt(j);
    217            changed = true;
    218        }
    219    }
    220    return changed;
    221 }
    222 
    223 UBool UVector::retainAll(const UVector& other) {
    224    UBool changed = false;
    225    for (int32_t j=size()-1; j>=0; --j) {
    226        int32_t i = other.indexOf(elements[j]);
    227        if (i < 0) {
    228            removeElementAt(j);
    229            changed = true;
    230        }
    231    }
    232    return changed;
    233 }
    234 
    235 void UVector::removeElementAt(int32_t index) {
    236    void* e = orphanElementAt(index);
    237    if (e != nullptr && deleter != nullptr) {
    238        (*deleter)(e);
    239    }
    240 }
    241 
    242 UBool UVector::removeElement(void* obj) {
    243    int32_t i = indexOf(obj);
    244    if (i >= 0) {
    245        removeElementAt(i);
    246        return true;
    247    }
    248    return false;
    249 }
    250 
    251 void UVector::removeAllElements() {
    252    if (deleter != nullptr) {
    253        for (int32_t i=0; i<count; ++i) {
    254            if (elements[i].pointer != nullptr) {
    255                (*deleter)(elements[i].pointer);
    256            }
    257        }
    258    }
    259    count = 0;
    260 }
    261 
    262 UBool   UVector::equals(const UVector &other) const {
    263    int      i;
    264 
    265    if (this->count != other.count) {
    266        return false;
    267    }
    268    if (comparer == nullptr) {
    269        for (i=0; i<count; i++) {
    270            if (elements[i].pointer != other.elements[i].pointer) {
    271                return false;
    272            }
    273        }
    274    } else {
    275        UElement key;
    276        for (i=0; i<count; i++) {
    277            key.pointer = &other.elements[i];
    278            if (!(*comparer)(key, elements[i])) {
    279                return false;
    280            }
    281        }
    282    }
    283    return true;
    284 }
    285 
    286 
    287 
    288 int32_t UVector::indexOf(void* obj, int32_t startIndex) const {
    289    UElement key;
    290    key.pointer = obj;
    291    return indexOf(key, startIndex, HINT_KEY_POINTER);
    292 }
    293 
    294 int32_t UVector::indexOf(int32_t obj, int32_t startIndex) const {
    295    UElement key;
    296    key.integer = obj;
    297    return indexOf(key, startIndex, HINT_KEY_INTEGER);
    298 }
    299 
    300 int32_t UVector::indexOf(UElement key, int32_t startIndex, int8_t hint) const {
    301    if (comparer != nullptr) {
    302        for (int32_t i=startIndex; i<count; ++i) {
    303            if ((*comparer)(key, elements[i])) {
    304                return i;
    305            }
    306        }
    307    } else {
    308        for (int32_t i=startIndex; i<count; ++i) {
    309            /* Pointers are not always the same size as ints so to perform
    310             * a valid comparison we need to know whether we are being
    311             * provided an int or a pointer. */
    312            if (hint & HINT_KEY_POINTER) {
    313                if (key.pointer == elements[i].pointer) {
    314                    return i;
    315                }
    316            } else {
    317                if (key.integer == elements[i].integer) {
    318                    return i;
    319                }
    320            }
    321        }
    322    }
    323    return -1;
    324 }
    325 
    326 UBool UVector::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) {
    327    if (U_FAILURE(status)) {
    328        return false;
    329    }
    330    if (minimumCapacity < 0) {
    331        status = U_ILLEGAL_ARGUMENT_ERROR;
    332        return false;
    333    }
    334    if (capacity < minimumCapacity) {
    335        if (capacity > (INT32_MAX - 1) / 2) {        	// integer overflow check
    336            status = U_ILLEGAL_ARGUMENT_ERROR;
    337            return false;
    338        }
    339        int32_t newCap = capacity * 2;
    340        if (newCap < minimumCapacity) {
    341            newCap = minimumCapacity;
    342        }
    343        if (newCap > static_cast<int32_t>(INT32_MAX / sizeof(UElement))) { // integer overflow check
    344            // We keep the original memory contents on bad minimumCapacity.
    345            status = U_ILLEGAL_ARGUMENT_ERROR;
    346            return false;
    347        }
    348        UElement* newElems = static_cast<UElement*>(uprv_realloc(elements, sizeof(UElement) * newCap));
    349        if (newElems == nullptr) {
    350            // We keep the original contents on the memory failure on realloc or bad minimumCapacity.
    351            status = U_MEMORY_ALLOCATION_ERROR;
    352            return false;
    353        }
    354        elements = newElems;
    355        capacity = newCap;
    356    }
    357    return true;
    358 }
    359 
    360 /**
    361 * Change the size of this vector as follows: If newSize is smaller,
    362 * then truncate the array, possibly deleting held elements for i >=
    363 * newSize.  If newSize is larger, grow the array, filling in new
    364 * slots with nullptr.
    365 */
    366 void UVector::setSize(int32_t newSize, UErrorCode &status) {
    367    if (!ensureCapacity(newSize, status)) {
    368        return;
    369    }
    370    if (newSize > count) {
    371        UElement empty;
    372        empty.pointer = nullptr;
    373        empty.integer = 0;
    374        for (int32_t i=count; i<newSize; ++i) {
    375            elements[i] = empty;
    376        }
    377    } else {
    378        /* Most efficient to count down */
    379        for (int32_t i=count-1; i>=newSize; --i) {
    380            removeElementAt(i);
    381        }
    382    }
    383    count = newSize;
    384 }
    385 
    386 /**
    387 * Fill in the given array with all elements of this vector.
    388 */
    389 void** UVector::toArray(void** result) const {
    390    void** a = result;
    391    for (int i=0; i<count; ++i) {
    392        *a++ = elements[i].pointer;
    393    }
    394    return result;
    395 }
    396 
    397 UObjectDeleter *UVector::setDeleter(UObjectDeleter *d) {
    398    UObjectDeleter *old = deleter;
    399    deleter = d;
    400    return old;
    401 }
    402 
    403 UElementsAreEqual *UVector::setComparer(UElementsAreEqual *d) {
    404    UElementsAreEqual *old = comparer;
    405    comparer = d;
    406    return old;
    407 }
    408 
    409 /**
    410 * Removes the element at the given index from this vector and
    411 * transfer ownership of it to the caller.  After this call, the
    412 * caller owns the result and must delete it and the vector entry
    413 * at 'index' is removed, shifting all subsequent entries back by
    414 * one index and shortening the size of the vector by one.  If the
    415 * index is out of range or if there is no item at the given index
    416 * then 0 is returned and the vector is unchanged.
    417 */
    418 void* UVector::orphanElementAt(int32_t index) {
    419    void* e = nullptr;
    420    if (0 <= index && index < count) {
    421        e = elements[index].pointer;
    422        for (int32_t i=index; i<count-1; ++i) {
    423            elements[i] = elements[i+1];
    424        }
    425        --count;
    426    }
    427    /* else index out of range */
    428    return e;
    429 }
    430 
    431 /**
    432 * Insert the given object into this vector at its sorted position
    433 * as defined by 'compare'.  The current elements are assumed to
    434 * be sorted already.
    435 */
    436 void UVector::sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec) {
    437    UElement e;
    438    e.pointer = obj;
    439    sortedInsert(e, compare, ec);
    440 }
    441 
    442 /**
    443 * Insert the given integer into this vector at its sorted position
    444 * as defined by 'compare'.  The current elements are assumed to
    445 * be sorted already.
    446 */
    447 void UVector::sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec) {
    448    U_ASSERT(deleter == nullptr);
    449    UElement e {};
    450    e.integer = obj;
    451    sortedInsert(e, compare, ec);
    452 }
    453 
    454 // ASSUME elements[] IS CURRENTLY SORTED
    455 void UVector::sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec) {
    456    // Perform a binary search for the location to insert tok at.  Tok
    457    // will be inserted between two elements a and b such that a <=
    458    // tok && tok < b, where there is a 'virtual' elements[-1] always
    459    // less than tok and a 'virtual' elements[count] always greater
    460    // than tok.
    461    if (!ensureCapacity(count + 1, ec)) {
    462        if (deleter != nullptr) {
    463            (*deleter)(e.pointer);
    464        }
    465        return;
    466    }
    467    int32_t min = 0, max = count;
    468    while (min != max) {
    469        int32_t probe = (min + max) / 2;
    470        int32_t c = (*compare)(elements[probe], e);
    471        if (c > 0) {
    472            max = probe;
    473        } else {
    474            // assert(c <= 0);
    475            min = probe + 1;
    476        }
    477    }
    478    for (int32_t i=count; i>min; --i) {
    479        elements[i] = elements[i-1];
    480    }
    481    elements[min] = e;
    482    ++count;
    483 }
    484 
    485 /**
    486  *  Array sort comparator function.
    487  *  Used from UVector::sort()
    488  *  Conforms to function signature required for uprv_sortArray().
    489  *  This function is essentially just a wrapper, to make a
    490  *  UVector style comparator function usable with uprv_sortArray().
    491  *
    492  *  The context pointer to this function is a pointer back
    493  *  (with some extra indirection) to the user supplied comparator.
    494  *  
    495  */
    496 static int32_t U_CALLCONV
    497 sortComparator(const void *context, const void *left, const void *right) {
    498    UElementComparator *compare = *static_cast<UElementComparator * const *>(context);
    499    UElement e1 = *static_cast<const UElement *>(left);
    500    UElement e2 = *static_cast<const UElement *>(right);
    501    int32_t result = (*compare)(e1, e2);
    502    return result;
    503 }
    504 
    505 
    506 /**
    507  *  Array sort comparison function for use from UVector::sorti()
    508  *  Compares int32_t vector elements.
    509  */
    510 static int32_t U_CALLCONV
    511 sortiComparator(const void * /*context */, const void *left, const void *right) {
    512    const UElement *e1 = static_cast<const UElement *>(left);
    513    const UElement *e2 = static_cast<const UElement *>(right);
    514    int32_t result = e1->integer < e2->integer? -1 :
    515                     e1->integer == e2->integer? 0 : 1;
    516    return result;
    517 }
    518 
    519 /**
    520  * Sort the vector, assuming it contains ints.
    521  *     (A more general sort would take a comparison function, but it's
    522  *     not clear whether UVector's UElementComparator or
    523  *     UComparator from uprv_sortAray would be more appropriate.)
    524  */
    525 void UVector::sorti(UErrorCode &ec) {
    526    if (U_SUCCESS(ec)) {
    527        uprv_sortArray(elements, count, sizeof(UElement),
    528                       sortiComparator, nullptr,  false, &ec);
    529    }
    530 }
    531 
    532 
    533 /**
    534 *  Sort with a user supplied comparator.
    535 *
    536 *    The comparator function handling is confusing because the function type
    537 *    for UVector  (as defined for sortedInsert()) is different from the signature
    538 *    required by uprv_sortArray().  This is handled by passing the
    539 *    the UVector sort function pointer via the context pointer to a
    540 *    sortArray() comparator function, which can then call back to
    541 *    the original user function.
    542 *
    543 *    An additional twist is that it's not safe to pass a pointer-to-function
    544 *    as  a (void *) data pointer, so instead we pass a (data) pointer to a
    545 *    pointer-to-function variable.
    546 */
    547 void UVector::sort(UElementComparator *compare, UErrorCode &ec) {
    548    if (U_SUCCESS(ec)) {
    549        uprv_sortArray(elements, count, sizeof(UElement),
    550                       sortComparator, &compare, false, &ec);
    551    }
    552 }
    553 
    554 
    555 /**
    556 *  Stable sort with a user supplied comparator of type UComparator.
    557 */
    558 void UVector::sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec) {
    559    if (U_SUCCESS(ec)) {
    560        uprv_sortArray(elements, count, sizeof(UElement),
    561                       compare, context, true, &ec);
    562    }
    563 }
    564 
    565 U_NAMESPACE_END