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