mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-10 07:39:16 +00:00
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:
parent
9c23e724ee
commit
baf94c23e2
2 changed files with 575 additions and 0 deletions
275
icu4c/source/common/uvectr32.cpp
Normal file
275
icu4c/source/common/uvectr32.cpp
Normal 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
|
||||
|
300
icu4c/source/common/uvectr32.h
Normal file
300
icu4c/source/common/uvectr32.h
Normal 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
|
Loading…
Add table
Reference in a new issue