michael@0: /* michael@0: ********************************************************************** michael@0: * Copyright (C) 1999-2011, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ********************************************************************** michael@0: */ michael@0: michael@0: // michael@0: // UVector32 is a class implementing a vector of 32 bit integers. michael@0: // It is similar to UVector, but holds int32_t values rather than pointers. michael@0: // Most of the code is unchanged from UVector. michael@0: // michael@0: michael@0: #ifndef UVECTOR32_H michael@0: #define UVECTOR32_H michael@0: michael@0: #include "unicode/utypes.h" michael@0: #include "unicode/uobject.h" michael@0: #include "uhash.h" michael@0: #include "uassert.h" michael@0: michael@0: U_NAMESPACE_BEGIN michael@0: michael@0: michael@0: michael@0: /** michael@0: *
Ultralightweight C++ implementation of a void* vector michael@0: * that is (mostly) compatible with java.util.Vector. michael@0: * michael@0: *
This is a very simple implementation, written to satisfy an michael@0: * immediate porting need. As such, it is not completely fleshed out, michael@0: * and it aims for simplicity and conformity. Nonetheless, it serves michael@0: * its purpose (porting code from java that uses java.util.Vector) michael@0: * well, and it could be easily made into a more robust vector class. michael@0: * michael@0: *
Design notes michael@0: * michael@0: *
There is index bounds checking, but little is done about it. If michael@0: * indices are out of bounds, either nothing happens, or zero is michael@0: * returned. We do avoid indexing off into the weeds. michael@0: * michael@0: *
There is detection of out of memory, but the handling is very michael@0: * coarse-grained -- similar to UnicodeString's protocol, but even michael@0: * coarser. The class contains one static flag that is set michael@0: * when any call to new returns zero. This allows the caller michael@0: * to use several vectors and make just one check at the end to see if michael@0: * a memory failure occurred. This is more efficient than making a michael@0: * check after each call on each vector when doing many operations on michael@0: * multiple vectors. The single static flag works best when memory michael@0: * failures are infrequent, and when recovery options are limited or michael@0: * nonexistent. michael@0: * michael@0: *
To do michael@0: * michael@0: *
Improve the handling of index out of bounds errors. michael@0: * michael@0: * @author Alan Liu michael@0: */ michael@0: class U_COMMON_API UVector32 : public UObject { michael@0: private: michael@0: int32_t count; michael@0: michael@0: int32_t capacity; michael@0: michael@0: int32_t maxCapacity; // Limit beyond which capacity is not permitted to grow. michael@0: michael@0: int32_t* elements; michael@0: michael@0: public: michael@0: UVector32(UErrorCode &status); michael@0: michael@0: UVector32(int32_t initialCapacity, UErrorCode &status); michael@0: michael@0: virtual ~UVector32(); michael@0: michael@0: /** michael@0: * Assign this object to another (make this a copy of 'other'). michael@0: * Use the 'assign' function to assign each element. michael@0: */ michael@0: void assign(const UVector32& other, UErrorCode &ec); michael@0: michael@0: /** michael@0: * Compare this vector with another. They will be considered michael@0: * equal if they are of the same size and all elements are equal, michael@0: * as compared using this object's comparer. michael@0: */ michael@0: UBool operator==(const UVector32& other); michael@0: michael@0: /** michael@0: * Equivalent to !operator==() michael@0: */ michael@0: inline UBool operator!=(const UVector32& other); michael@0: michael@0: //------------------------------------------------------------ michael@0: // java.util.Vector API michael@0: //------------------------------------------------------------ michael@0: michael@0: void addElement(int32_t elem, UErrorCode &status); michael@0: michael@0: void setElementAt(int32_t elem, int32_t index); michael@0: michael@0: void insertElementAt(int32_t elem, int32_t index, UErrorCode &status); michael@0: michael@0: int32_t elementAti(int32_t index) const; michael@0: michael@0: UBool equals(const UVector32 &other) const; michael@0: michael@0: int32_t lastElementi(void) const; michael@0: michael@0: int32_t indexOf(int32_t elem, int32_t startIndex = 0) const; michael@0: michael@0: UBool contains(int32_t elem) const; michael@0: michael@0: UBool containsAll(const UVector32& other) const; michael@0: michael@0: UBool removeAll(const UVector32& other); michael@0: michael@0: UBool retainAll(const UVector32& other); michael@0: michael@0: void removeElementAt(int32_t index); michael@0: michael@0: void removeAllElements(); michael@0: michael@0: int32_t size(void) const; michael@0: michael@0: UBool isEmpty(void) const; michael@0: michael@0: // Inline. Use this one for speedy size check. michael@0: inline UBool ensureCapacity(int32_t minimumCapacity, UErrorCode &status); michael@0: michael@0: // Out-of-line, handles actual growth. Called by ensureCapacity() when necessary. michael@0: UBool expandCapacity(int32_t minimumCapacity, UErrorCode &status); michael@0: michael@0: /** michael@0: * Change the size of this vector as follows: If newSize is michael@0: * smaller, then truncate the array, possibly deleting held michael@0: * elements for i >= newSize. If newSize is larger, grow the michael@0: * array, filling in new slows with zero. michael@0: */ michael@0: void setSize(int32_t newSize); michael@0: michael@0: //------------------------------------------------------------ michael@0: // New API michael@0: //------------------------------------------------------------ michael@0: michael@0: /** michael@0: * Returns true if this vector contains none of the elements michael@0: * of the given vector. michael@0: * @param other vector to be checked for containment michael@0: * @return true if the test condition is met michael@0: */ michael@0: UBool containsNone(const UVector32& other) const; michael@0: michael@0: michael@0: /** michael@0: * Insert the given integer into this vector at its sorted position. michael@0: * The current elements are assumed to be sorted already. michael@0: */ michael@0: void sortedInsert(int32_t elem, UErrorCode& ec); michael@0: michael@0: /** michael@0: * Returns a pointer to the internal array holding the vector. michael@0: */ michael@0: int32_t *getBuffer() const; michael@0: michael@0: /** michael@0: * Set the maximum allowed buffer capacity for this vector/stack. michael@0: * Default with no limit set is unlimited, go until malloc() fails. michael@0: * A Limit of zero means unlimited capacity. michael@0: * Units are vector elements (32 bits each), not bytes. michael@0: */ michael@0: void setMaxCapacity(int32_t limit); michael@0: michael@0: /** michael@0: * ICU "poor man's RTTI", returns a UClassID for this class. michael@0: */ michael@0: static UClassID U_EXPORT2 getStaticClassID(); michael@0: michael@0: /** michael@0: * ICU "poor man's RTTI", returns a UClassID for the actual class. michael@0: */ michael@0: virtual UClassID getDynamicClassID() const; michael@0: michael@0: private: michael@0: void _init(int32_t initialCapacity, UErrorCode &status); michael@0: michael@0: // Disallow michael@0: UVector32(const UVector32&); michael@0: michael@0: // Disallow michael@0: UVector32& operator=(const UVector32&); michael@0: michael@0: michael@0: // API Functions for Stack operations. michael@0: // In the original UVector, these were in a separate derived class, UStack. michael@0: // Here in UVector32, they are all together. michael@0: public: michael@0: UBool empty(void) const; // TODO: redundant, same as empty(). Remove it? michael@0: michael@0: int32_t peeki(void) const; michael@0: michael@0: int32_t popi(void); michael@0: michael@0: int32_t push(int32_t i, UErrorCode &status); michael@0: michael@0: int32_t *reserveBlock(int32_t size, UErrorCode &status); michael@0: int32_t *popFrame(int32_t size); michael@0: }; michael@0: michael@0: michael@0: // UVector32 inlines michael@0: michael@0: inline UBool UVector32::ensureCapacity(int32_t minimumCapacity, UErrorCode &status) { michael@0: if ((minimumCapacity >= 0) && (capacity >= minimumCapacity)) { michael@0: return TRUE; michael@0: } else { michael@0: return expandCapacity(minimumCapacity, status); michael@0: } michael@0: } michael@0: michael@0: inline int32_t UVector32::elementAti(int32_t index) const { michael@0: return (index >= 0 && count > 0 && count - index > 0) ? elements[index] : 0; michael@0: } michael@0: michael@0: michael@0: inline void UVector32::addElement(int32_t elem, UErrorCode &status) { michael@0: if (ensureCapacity(count + 1, status)) { michael@0: elements[count] = elem; michael@0: count++; michael@0: } michael@0: } michael@0: michael@0: inline int32_t *UVector32::reserveBlock(int32_t size, UErrorCode &status) { michael@0: if (ensureCapacity(count+size, status) == FALSE) { michael@0: return NULL; michael@0: } michael@0: int32_t *rp = elements+count; michael@0: count += size; michael@0: return rp; michael@0: } michael@0: michael@0: inline int32_t *UVector32::popFrame(int32_t size) { michael@0: U_ASSERT(count >= size); michael@0: count -= size; michael@0: if (count < 0) { michael@0: count = 0; michael@0: } michael@0: return elements+count-size; michael@0: } michael@0: michael@0: michael@0: michael@0: inline int32_t UVector32::size(void) const { michael@0: return count; michael@0: } michael@0: michael@0: inline UBool UVector32::isEmpty(void) const { michael@0: return count == 0; michael@0: } michael@0: michael@0: inline UBool UVector32::contains(int32_t obj) const { michael@0: return indexOf(obj) >= 0; michael@0: } michael@0: michael@0: inline int32_t UVector32::lastElementi(void) const { michael@0: return elementAti(count-1); michael@0: } michael@0: michael@0: inline UBool UVector32::operator!=(const UVector32& other) { michael@0: return !operator==(other); michael@0: } michael@0: michael@0: inline int32_t *UVector32::getBuffer() const { michael@0: return elements; michael@0: } michael@0: michael@0: michael@0: // UStack inlines michael@0: michael@0: inline UBool UVector32::empty(void) const { michael@0: return isEmpty(); michael@0: } michael@0: michael@0: inline int32_t UVector32::peeki(void) const { michael@0: return lastElementi(); michael@0: } michael@0: michael@0: inline int32_t UVector32::push(int32_t i, UErrorCode &status) { michael@0: addElement(i, status); michael@0: return i; michael@0: } michael@0: michael@0: inline int32_t UVector32::popi(void) { michael@0: int32_t result = 0; michael@0: if (count > 0) { michael@0: count--; michael@0: result = elements[count]; michael@0: } michael@0: return result; michael@0: } michael@0: michael@0: U_NAMESPACE_END michael@0: michael@0: #endif