michael@0: /* michael@0: ********************************************************************** michael@0: * Copyright (C) 1999-2010, International Business Machines michael@0: * Corporation and others. All Rights Reserved. michael@0: ********************************************************************** michael@0: */ michael@0: michael@0: // michael@0: // UVector64 is a class implementing a vector of 64 bit integers. michael@0: // It is similar to UVector32, but holds int64_t values rather than int32_t. michael@0: // Most of the code is unchanged from UVector. michael@0: // michael@0: michael@0: #ifndef UVECTOR64_H michael@0: #define UVECTOR64_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 an int64_t vector michael@0: * that has a subset of methods from UVector32 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: */ michael@0: class U_COMMON_API UVector64 : 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: int64_t* elements; michael@0: michael@0: public: michael@0: UVector64(UErrorCode &status); michael@0: michael@0: UVector64(int32_t initialCapacity, UErrorCode &status); michael@0: michael@0: virtual ~UVector64(); 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 UVector64& 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 UVector64& other); michael@0: michael@0: /** michael@0: * Equivalent to !operator==() michael@0: */ michael@0: inline UBool operator!=(const UVector64& other); michael@0: michael@0: //------------------------------------------------------------ michael@0: // subset of java.util.Vector API michael@0: //------------------------------------------------------------ michael@0: michael@0: void addElement(int64_t elem, UErrorCode &status); michael@0: michael@0: void setElementAt(int64_t elem, int32_t index); michael@0: michael@0: void insertElementAt(int64_t elem, int32_t index, UErrorCode &status); michael@0: michael@0: int64_t elementAti(int32_t index) const; michael@0: michael@0: //UBool equals(const UVector64 &other) const; michael@0: michael@0: int64_t lastElementi(void) const; michael@0: michael@0: //int32_t indexOf(int64_t elem, int32_t startIndex = 0) const; michael@0: michael@0: //UBool contains(int64_t elem) const; michael@0: michael@0: //UBool containsAll(const UVector64& other) const; michael@0: michael@0: //UBool removeAll(const UVector64& other); michael@0: michael@0: //UBool retainAll(const UVector64& 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: //UBool containsNone(const UVector64& other) const; michael@0: michael@0: michael@0: //void sortedInsert(int64_t elem, UErrorCode& ec); michael@0: michael@0: /** michael@0: * Returns a pointer to the internal array holding the vector. michael@0: */ michael@0: int64_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 (64 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: UVector64(const UVector64&); michael@0: michael@0: // Disallow michael@0: UVector64& operator=(const UVector64&); 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 UVector64, they are all together. michael@0: public: michael@0: //UBool empty(void) const; // TODO: redundant, same as empty(). Remove it? michael@0: michael@0: //int64_t peeki(void) const; michael@0: michael@0: int64_t popi(void); michael@0: michael@0: int64_t push(int64_t i, UErrorCode &status); michael@0: michael@0: int64_t *reserveBlock(int32_t size, UErrorCode &status); michael@0: int64_t *popFrame(int32_t size); michael@0: }; michael@0: michael@0: michael@0: // UVector64 inlines michael@0: michael@0: inline UBool UVector64::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 int64_t UVector64::elementAti(int32_t index) const { michael@0: return (0 <= index && index < count) ? elements[index] : 0; michael@0: } michael@0: michael@0: michael@0: inline void UVector64::addElement(int64_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 int64_t *UVector64::reserveBlock(int32_t size, UErrorCode &status) { michael@0: if (ensureCapacity(count+size, status) == FALSE) { michael@0: return NULL; michael@0: } michael@0: int64_t *rp = elements+count; michael@0: count += size; michael@0: return rp; michael@0: } michael@0: michael@0: inline int64_t *UVector64::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 UVector64::size(void) const { michael@0: return count; michael@0: } michael@0: michael@0: inline int64_t UVector64::lastElementi(void) const { michael@0: return elementAti(count-1); michael@0: } michael@0: michael@0: inline UBool UVector64::operator!=(const UVector64& other) { michael@0: return !operator==(other); michael@0: } michael@0: michael@0: inline int64_t *UVector64::getBuffer() const { michael@0: return elements; michael@0: } michael@0: michael@0: michael@0: // UStack inlines michael@0: michael@0: inline int64_t UVector64::push(int64_t i, UErrorCode &status) { michael@0: addElement(i, status); michael@0: return i; michael@0: } michael@0: michael@0: inline int64_t UVector64::popi(void) { michael@0: int64_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