Home | History | Annotate | Download | only in common
      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-2016, International Business Machines
      6 *   Corporation and others.  All Rights Reserved.
      7 **********************************************************************
      8 *   Date        Name        Description
      9 *   10/22/99    alan        Creation.  This is an internal header.
     10 *                           It should not be exported.
     11 **********************************************************************
     12 */
     13 
     14 #ifndef UVECTOR_H
     15 #define UVECTOR_H
     16 
     17 #include "unicode/utypes.h"
     18 #include "unicode/uobject.h"
     19 #include "cmemory.h"
     20 #include "uarrsort.h"
     21 #include "uelement.h"
     22 
     23 U_NAMESPACE_BEGIN
     24 
     25 /**
     26  * <p>Ultralightweight C++ implementation of a <tt>void*</tt> vector
     27  * that is (mostly) compatible with java.util.Vector.
     28  *
     29  * <p>This is a very simple implementation, written to satisfy an
     30  * immediate porting need.  As such, it is not completely fleshed out,
     31  * and it aims for simplicity and conformity.  Nonetheless, it serves
     32  * its purpose (porting code from java that uses java.util.Vector)
     33  * well, and it could be easily made into a more robust vector class.
     34  *
     35  * <p><b>Design notes</b>
     36  *
     37  * <p>There is index bounds checking, but little is done about it.  If
     38  * indices are out of bounds, either nothing happens, or zero is
     39  * returned.  We <em>do</em> avoid indexing off into the weeds.
     40  *
     41  * <p>There is detection of out of memory, but the handling is very
     42  * coarse-grained -- similar to UnicodeString's protocol, but even
     43  * coarser.  The class contains <em>one static flag</em> that is set
     44  * when any call to <tt>new</tt> returns zero.  This allows the caller
     45  * to use several vectors and make just one check at the end to see if
     46  * a memory failure occurred.  This is more efficient than making a
     47  * check after each call on each vector when doing many operations on
     48  * multiple vectors.  The single static flag works best when memory
     49  * failures are infrequent, and when recovery options are limited or
     50  * nonexistent.
     51  *
     52  * <p>Since we don't have garbage collection, UVector was given the
     53  * option to <em>own</em>its contents.  To employ this, set a deleter
     54  * function.  The deleter is called on a void* pointer when that
     55  * pointer is released by the vector, either when the vector itself is
     56  * destructed, or when a call to setElementAt() overwrites an element,
     57  * or when a call to remove() or one of its variants explicitly
     58  * removes an element.  If no deleter is set, or the deleter is set to
     59  * zero, then it is assumed that the caller will delete elements as
     60  * needed.
     61  *
     62  * <p>In order to implement methods such as contains() and indexOf(),
     63  * UVector needs a way to compare objects for equality.  To do so, it
     64  * uses a comparison function, or "comparer."  If the comparer is not
     65  * set, or is set to zero, then all such methods will act as if the
     66  * vector contains no element.  That is, indexOf() will always return
     67  * -1, contains() will always return FALSE, etc.
     68  *
     69  * <p><b>To do</b>
     70  *
     71  * <p>Improve the handling of index out of bounds errors.
     72  *
     73  * @author Alan Liu
     74  */
     75 class U_COMMON_API UVector : public UObject {
     76     // NOTE: UVector uses the UHashKey (union of void* and int32_t) as
     77     // its basic storage type.  It uses UElementsAreEqual as its
     78     // comparison function.  It uses UObjectDeleter as its deleter
     79     // function.  These are named for hashtables, but used here as-is
     80     // rather than duplicating the type.  This allows sharing of
     81     // support functions.
     82 
     83 private:
     84     int32_t count;
     85 
     86     int32_t capacity;
     87 
     88     UElement* elements;
     89 
     90     UObjectDeleter *deleter;
     91 
     92     UElementsAreEqual *comparer;
     93 
     94 public:
     95     UVector(UErrorCode &status);
     96 
     97     UVector(int32_t initialCapacity, UErrorCode &status);
     98 
     99     UVector(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status);
    100 
    101     UVector(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status);
    102 
    103     virtual ~UVector();
    104 
    105     /**
    106      * Assign this object to another (make this a copy of 'other').
    107      * Use the 'assign' function to assign each element.
    108      */
    109     void assign(const UVector& other, UElementAssigner *assign, UErrorCode &ec);
    110 
    111     /**
    112      * Compare this vector with another.  They will be considered
    113      * equal if they are of the same size and all elements are equal,
    114      * as compared using this object's comparer.
    115      */
    116     UBool operator==(const UVector& other);
    117 
    118     /**
    119      * Equivalent to !operator==()
    120      */
    121     inline UBool operator!=(const UVector& other);
    122 
    123     //------------------------------------------------------------
    124     // java.util.Vector API
    125     //------------------------------------------------------------
    126 
    127     void addElement(void* obj, UErrorCode &status);
    128 
    129     void addElement(int32_t elem, UErrorCode &status);
    130 
    131     void setElementAt(void* obj, int32_t index);
    132 
    133     void setElementAt(int32_t elem, int32_t index);
    134 
    135     void insertElementAt(void* obj, int32_t index, UErrorCode &status);
    136 
    137     void insertElementAt(int32_t elem, int32_t index, UErrorCode &status);
    138 
    139     void* elementAt(int32_t index) const;
    140 
    141     int32_t elementAti(int32_t index) const;
    142 
    143     UBool equals(const UVector &other) const;
    144 
    145     void* firstElement(void) const;
    146 
    147     void* lastElement(void) const;
    148 
    149     int32_t lastElementi(void) const;
    150 
    151     int32_t indexOf(void* obj, int32_t startIndex = 0) const;
    152 
    153     int32_t indexOf(int32_t obj, int32_t startIndex = 0) const;
    154 
    155     UBool contains(void* obj) const;
    156 
    157     UBool contains(int32_t obj) const;
    158 
    159     UBool containsAll(const UVector& other) const;
    160 
    161     UBool removeAll(const UVector& other);
    162 
    163     UBool retainAll(const UVector& other);
    164 
    165     void removeElementAt(int32_t index);
    166 
    167     UBool removeElement(void* obj);
    168 
    169     void removeAllElements();
    170 
    171     int32_t size(void) const;
    172 
    173     UBool isEmpty(void) const;
    174 
    175     UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status);
    176 
    177     /**
    178      * Change the size of this vector as follows: If newSize is
    179      * smaller, then truncate the array, possibly deleting held
    180      * elements for i >= newSize.  If newSize is larger, grow the
    181      * array, filling in new slots with NULL.
    182      */
    183     void setSize(int32_t newSize, UErrorCode &status);
    184 
    185     /**
    186      * Fill in the given array with all elements of this vector.
    187      */
    188     void** toArray(void** result) const;
    189 
    190     //------------------------------------------------------------
    191     // New API
    192     //------------------------------------------------------------
    193 
    194     UObjectDeleter *setDeleter(UObjectDeleter *d);
    195 
    196     UElementsAreEqual *setComparer(UElementsAreEqual *c);
    197 
    198     void* operator[](int32_t index) const;
    199 
    200     /**
    201      * Removes the element at the given index from this vector and
    202      * transfer ownership of it to the caller.  After this call, the
    203      * caller owns the result and must delete it and the vector entry
    204      * at 'index' is removed, shifting all subsequent entries back by
    205      * one index and shortening the size of the vector by one.  If the
    206      * index is out of range or if there is no item at the given index
    207      * then 0 is returned and the vector is unchanged.
    208      */
    209     void* orphanElementAt(int32_t index);
    210 
    211     /**
    212      * Returns true if this vector contains none of the elements
    213      * of the given vector.
    214      * @param other vector to be checked for containment
    215      * @return true if the test condition is met
    216      */
    217     UBool containsNone(const UVector& other) const;
    218 
    219     /**
    220      * Insert the given object into this vector at its sorted position
    221      * as defined by 'compare'.  The current elements are assumed to
    222      * be sorted already.
    223      */
    224     void sortedInsert(void* obj, UElementComparator *compare, UErrorCode& ec);
    225 
    226     /**
    227      * Insert the given integer into this vector at its sorted position
    228      * as defined by 'compare'.  The current elements are assumed to
    229      * be sorted already.
    230      */
    231     void sortedInsert(int32_t obj, UElementComparator *compare, UErrorCode& ec);
    232 
    233     /**
    234      * Sort the contents of the vector, assuming that the contents of the
    235      * vector are of type int32_t.
    236      */
    237     void sorti(UErrorCode &ec);
    238 
    239     /**
    240       * Sort the contents of this vector, using a caller-supplied function
    241       * to do the comparisons.  (It's confusing that
    242       *  UVector's UElementComparator function is different from the
    243       *  UComparator function type defined in uarrsort.h)
    244       */
    245     void sort(UElementComparator *compare, UErrorCode &ec);
    246 
    247     /**
    248      * Stable sort the contents of this vector using a caller-supplied function
    249      * of type UComparator to do the comparison.  Provides more flexibility
    250      * than UVector::sort() because an additional user parameter can be passed to
    251      * the comparison function.
    252      */
    253     void sortWithUComparator(UComparator *compare, const void *context, UErrorCode &ec);
    254 
    255     /**
    256      * ICU "poor man's RTTI", returns a UClassID for this class.
    257      */
    258     static UClassID U_EXPORT2 getStaticClassID();
    259 
    260     /**
    261      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    262      */
    263     virtual UClassID getDynamicClassID() const;
    264 
    265 private:
    266     void _init(int32_t initialCapacity, UErrorCode &status);
    267 
    268     int32_t indexOf(UElement key, int32_t startIndex = 0, int8_t hint = 0) const;
    269 
    270     void sortedInsert(UElement e, UElementComparator *compare, UErrorCode& ec);
    271 
    272     // Disallow
    273     UVector(const UVector&);
    274 
    275     // Disallow
    276     UVector& operator=(const UVector&);
    277 
    278 };
    279 
    280 
    281 /**
    282  * <p>Ultralightweight C++ implementation of a <tt>void*</tt> stack
    283  * that is (mostly) compatible with java.util.Stack.  As in java, this
    284  * is merely a paper thin layer around UVector.  See the UVector
    285  * documentation for further information.
    286  *
    287  * <p><b>Design notes</b>
    288  *
    289  * <p>The element at index <tt>n-1</tt> is (of course) the top of the
    290  * stack.
    291  *
    292  * <p>The poorly named <tt>empty()</tt> method doesn't empty the
    293  * stack; it determines if the stack is empty.
    294  *
    295  * @author Alan Liu
    296  */
    297 class U_COMMON_API UStack : public UVector {
    298 public:
    299     UStack(UErrorCode &status);
    300 
    301     UStack(int32_t initialCapacity, UErrorCode &status);
    302 
    303     UStack(UObjectDeleter *d, UElementsAreEqual *c, UErrorCode &status);
    304 
    305     UStack(UObjectDeleter *d, UElementsAreEqual *c, int32_t initialCapacity, UErrorCode &status);
    306 
    307     virtual ~UStack();
    308 
    309     // It's okay not to have a virtual destructor (in UVector)
    310     // because UStack has no special cleanup to do.
    311 
    312     UBool empty(void) const;
    313 
    314     void* peek(void) const;
    315 
    316     int32_t peeki(void) const;
    317 
    318     void* pop(void);
    319 
    320     int32_t popi(void);
    321 
    322     void* push(void* obj, UErrorCode &status);
    323 
    324     int32_t push(int32_t i, UErrorCode &status);
    325 
    326     /*
    327     If the object o occurs as an item in this stack,
    328     this method returns the 1-based distance from the top of the stack.
    329     */
    330     int32_t search(void* obj) const;
    331 
    332     /**
    333      * ICU "poor man's RTTI", returns a UClassID for this class.
    334      */
    335     static UClassID U_EXPORT2 getStaticClassID();
    336 
    337     /**
    338      * ICU "poor man's RTTI", returns a UClassID for the actual class.
    339      */
    340     virtual UClassID getDynamicClassID() const;
    341 
    342 private:
    343     // Disallow
    344     UStack(const UStack&);
    345 
    346     // Disallow
    347     UStack& operator=(const UStack&);
    348 };
    349 
    350 
    351 // UVector inlines
    352 
    353 inline int32_t UVector::size(void) const {
    354     return count;
    355 }
    356 
    357 inline UBool UVector::isEmpty(void) const {
    358     return count == 0;
    359 }
    360 
    361 inline UBool UVector::contains(void* obj) const {
    362     return indexOf(obj) >= 0;
    363 }
    364 
    365 inline UBool UVector::contains(int32_t obj) const {
    366     return indexOf(obj) >= 0;
    367 }
    368 
    369 inline void* UVector::firstElement(void) const {
    370     return elementAt(0);
    371 }
    372 
    373 inline void* UVector::lastElement(void) const {
    374     return elementAt(count-1);
    375 }
    376 
    377 inline int32_t UVector::lastElementi(void) const {
    378     return elementAti(count-1);
    379 }
    380 
    381 inline void* UVector::operator[](int32_t index) const {
    382     return elementAt(index);
    383 }
    384 
    385 inline UBool UVector::operator!=(const UVector& other) {
    386     return !operator==(other);
    387 }
    388 
    389 // UStack inlines
    390 
    391 inline UBool UStack::empty(void) const {
    392     return isEmpty();
    393 }
    394 
    395 inline void* UStack::peek(void) const {
    396     return lastElement();
    397 }
    398 
    399 inline int32_t UStack::peeki(void) const {
    400     return lastElementi();
    401 }
    402 
    403 inline void* UStack::push(void* obj, UErrorCode &status) {
    404     addElement(obj, status);
    405     return obj;
    406 }
    407 
    408 inline int32_t UStack::push(int32_t i, UErrorCode &status) {
    409     addElement(i, status);
    410     return i;
    411 }
    412 
    413 U_NAMESPACE_END
    414 
    415 #endif
    416