ICU-2420 regexp perf, add UVector32 class - vector of uint32_t. Allows optimizations

not possible with original (pointer sized) UVector class.

X-SVN-Rev: 10826
This commit is contained in:
Andy Heninger 2003-01-08 23:40:45 +00:00
parent 9c23e724ee
commit baf94c23e2
2 changed files with 575 additions and 0 deletions

View file

@ -0,0 +1,275 @@
/*
******************************************************************************
* Copyright (C) 1999-2003, International Business Machines Corporation and *
* others. All Rights Reserved. *
******************************************************************************
* Date Name Description
* 10/22/99 alan Creation.
**********************************************************************
*/
#include "uvectr32.h"
#include "cmemory.h"
U_NAMESPACE_BEGIN
#define DEFUALT_CAPACITY 8
/*
* Constants for hinting whether a key is an integer
* or a pointer. If a hint bit is zero, then the associated
* token is assumed to be an integer. This is needed for iSeries
*/
#define HINT_KEY_POINTER (1)
#define HINT_KEY_INTEGER (0)
const char UVector32::fgClassID=0;
UVector32::UVector32(UErrorCode &status) :
count(0),
capacity(0),
elements(NULL)
{
_init(DEFUALT_CAPACITY, status);
}
UVector32::UVector32(int32_t initialCapacity, UErrorCode &status) :
count(0),
capacity(0),
elements(0)
{
_init(initialCapacity, status);
}
void UVector32::_init(int32_t initialCapacity, UErrorCode &status) {
// Fix bogus initialCapacity values; avoid malloc(0)
if (initialCapacity < 1) {
initialCapacity = DEFUALT_CAPACITY;
}
elements = (int32_t *)uprv_malloc(sizeof(int32_t)*initialCapacity);
if (elements == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
} else {
capacity = initialCapacity;
}
}
UVector32::~UVector32() {
uprv_free(elements);
elements = 0;
}
/**
* Assign this object to another (make this a copy of 'other').
*/
void UVector32::assign(const UVector32& other, UErrorCode &ec) {
if (ensureCapacity(other.count, ec)) {
setSize(other.count);
for (int32_t i=0; i<other.count; ++i) {
elements[i] = other.elements[i];
}
}
}
UBool UVector32::operator==(const UVector32& other) {
int32_t i;
if (count != other.count) return FALSE;
for (i=0; i<count; ++i) {
if (elements[i] != other.elements[i]) {
return FALSE;
}
}
return TRUE;
}
void UVector32::setElementAt(int32_t elem, int32_t index) {
if (0 <= index && index < count) {
elements[index] = elem;
}
/* else index out of range */
}
void UVector32::insertElementAt(int32_t elem, int32_t index, UErrorCode &status) {
// must have 0 <= index <= count
if (0 <= index && index <= count && ensureCapacity(count + 1, status)) {
for (int32_t i=count; i>index; --i) {
elements[i] = elements[i-1];
}
elements[index] = elem;
++count;
}
/* else index out of range */
}
UBool UVector32::containsAll(const UVector32& other) const {
for (int32_t i=0; i<other.size(); ++i) {
if (indexOf(other.elements[i]) < 0) {
return FALSE;
}
}
return TRUE;
}
UBool UVector32::containsNone(const UVector32& other) const {
for (int32_t i=0; i<other.size(); ++i) {
if (indexOf(other.elements[i]) >= 0) {
return FALSE;
}
}
return TRUE;
}
UBool UVector32::removeAll(const UVector32& other) {
UBool changed = FALSE;
for (int32_t i=0; i<other.size(); ++i) {
int32_t j = indexOf(other.elements[i]);
if (j >= 0) {
removeElementAt(j);
changed = TRUE;
}
}
return changed;
}
UBool UVector32::retainAll(const UVector32& other) {
UBool changed = FALSE;
for (int32_t j=size()-1; j>=0; --j) {
int32_t i = other.indexOf(elements[j]);
if (i < 0) {
removeElementAt(j);
changed = TRUE;
}
}
return changed;
}
void UVector32::removeElementAt(int32_t index) {
if (index >= 0) {
for (int32_t i=index; i<count-1; ++i) {
elements[i] = elements[i+1];
}
--count;
}
}
void UVector32::removeAllElements(void) {
count = 0;
}
UBool UVector32::equals(const UVector32 &other) const {
int i;
if (this->count != other.count) {
return FALSE;
}
for (i=0; i<count; i++) {
if (elements[i] != other.elements[i]) {
return FALSE;
}
}
return TRUE;
}
int32_t UVector32::indexOf(int32_t key, int32_t startIndex) const {
int32_t i;
for (i=startIndex; i<count; ++i) {
if (key == elements[i]) {
return i;
}
}
return -1;
}
UBool UVector32::expandCapacity(int32_t minimumCapacity, UErrorCode &status) {
if (capacity >= minimumCapacity) {
return TRUE;
} else {
int32_t newCap = capacity * 2;
if (newCap < minimumCapacity) {
newCap = minimumCapacity;
}
int32_t* newElems = (int32_t *)uprv_malloc(sizeof(int32_t)*newCap);
if (newElems == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return FALSE;
}
uprv_memcpy(newElems, elements, sizeof(elements[0]) * count);
uprv_free(elements);
elements = newElems;
capacity = newCap;
return TRUE;
}
}
/**
* Change the size of this vector as follows: If newSize is smaller,
* then truncate the array, possibly deleting held elements for i >=
* newSize. If newSize is larger, grow the array, filling in new
* slots with NULL.
*/
void UVector32::setSize(int32_t newSize) {
int32_t i;
if (newSize < 0) {
return;
}
if (newSize > count) {
UErrorCode ec = U_ZERO_ERROR;
if (!ensureCapacity(newSize, ec)) {
return;
}
for (i=count; i<newSize; ++i) {
elements[i] = 0;
}
}
count = newSize;
}
/**
* Insert the given integer into this vector at its sorted position
* as defined by 'compare'. The current elements are assumed to
* be sorted already.
*/
void UVector32::sortedInsert(int32_t tok, UErrorCode& ec) {
// Perform a binary search for the location to insert tok at. Tok
// will be inserted between two elements a and b such that a <=
// tok && tok < b, where there is a 'virtual' elements[-1] always
// less than tok and a 'virtual' elements[count] always greater
// than tok.
int32_t min = 0, max = count;
while (min != max) {
int32_t probe = (min + max) / 2;
//int8_t c = (*compare)(elements[probe], tok);
//if (c > 0) {
if (elements[probe] > tok) {
max = probe;
} else {
// assert(c <= 0);
min = probe + 1;
}
}
if (ensureCapacity(count + 1, ec)) {
for (int32_t i=count; i>min; --i) {
elements[i] = elements[i-1];
}
elements[min] = tok;
++count;
}
}
U_NAMESPACE_END

View file

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