ICU-1023 fix UVector to support int32_t elements properly

X-SVN-Rev: 5398
This commit is contained in:
Alan Liu 2001-07-31 18:10:53 +00:00
parent 63e908b597
commit 772c6a5bd5
4 changed files with 94 additions and 69 deletions

View File

@ -23,7 +23,7 @@ UVector::UVector(int32_t initialCapacity) :
_init(initialCapacity);
}
UVector::UVector(Deleter d, Comparer c, int32_t initialCapacity) :
UVector::UVector(UObjectDeleter d, UKeyComparator c, int32_t initialCapacity) :
count(0),
capacity(0),
elements(0),
@ -34,7 +34,7 @@ UVector::UVector(Deleter d, Comparer c, int32_t initialCapacity) :
}
void UVector::_init(int32_t initialCapacity) {
elements = new void*[initialCapacity];
elements = new UHashKey[initialCapacity];
if (elements == 0) {
outOfMemory = TRUE;
} else {
@ -50,16 +50,32 @@ UVector::~UVector() {
void UVector::addElement(void* obj) {
if (ensureCapacity(count + 1)) {
elements[count++] = obj;
elements[count++].pointer = obj;
}
}
void UVector::addElement(int32_t elem) {
if (ensureCapacity(count + 1)) {
elements[count++].integer = elem;
}
}
void UVector::setElementAt(void* obj, int32_t index) {
if (0 <= index && index < count) {
if (elements[index] != 0 && deleter != 0) {
(*deleter)(elements[index]);
if (elements[index].pointer != 0 && deleter != 0) {
(*deleter)(elements[index].pointer);
}
elements[index] = obj;
elements[index].pointer = obj;
}
/* else index out of range */
}
void UVector::setElementAt(int32_t elem, int32_t index) {
if (0 <= index && index < count) {
if (elements[index].pointer != 0 && deleter != 0) {
(*deleter)(elements[index].pointer);
}
elements[index].integer = elem;
}
/* else index out of range */
}
@ -70,13 +86,17 @@ void UVector::insertElementAt(void* obj, int32_t index) {
for (int32_t i=count; i>index; --i) {
elements[i] = elements[i-1];
}
elements[index] = obj;
elements[index].pointer = obj;
}
/* else index out of range */
}
void* UVector::elementAt(int32_t index) const {
return (0 <= index && index < count) ? elements[index] : 0;
return (0 <= index && index < count) ? elements[index].pointer : 0;
}
int32_t UVector::elementAti(int32_t index) const {
return (0 <= index && index < count) ? elements[index].integer : 0;
}
void UVector::removeElementAt(int32_t index) {
@ -98,8 +118,8 @@ UBool UVector::removeElement(void* obj) {
void UVector::removeAllElements(void) {
if (deleter != 0) {
for (int32_t i=0; i<count; ++i) {
if (elements[i] != 0) {
(*deleter)(elements[i]);
if (elements[i].pointer != 0) {
(*deleter)(elements[i].pointer);
}
}
}
@ -108,8 +128,10 @@ void UVector::removeAllElements(void) {
int32_t UVector::indexOf(void* obj, int32_t startIndex) const {
if (comparer != 0) {
UHashKey key;
key.pointer = obj;
for (int32_t i=startIndex; i<count; ++i) {
if ((*comparer)(obj, elements[i])) {
if ((*comparer)(key, elements[i])) {
return i;
}
}
@ -122,12 +144,12 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity) {
return TRUE;
} else {
int32_t newCap = capacity * 2;
void** newElems = new void*[newCap];
UHashKey* newElems = new UHashKey[newCap];
if (newElems == 0) {
outOfMemory = TRUE;
return FALSE;
}
uprv_memcpy(newElems, elements, sizeof(void*) * count);
uprv_memcpy(newElems, elements, sizeof(elements[0]) * count);
delete[] elements;
elements = newElems;
capacity = newCap;
@ -135,14 +157,14 @@ UBool UVector::ensureCapacity(int32_t minimumCapacity) {
}
}
UVector::Deleter UVector::setDeleter(Deleter d) {
Deleter old = deleter;
UObjectDeleter UVector::setDeleter(UObjectDeleter d) {
UObjectDeleter old = deleter;
deleter = d;
return old;
}
UVector::Comparer UVector::setComparer(Comparer d) {
Comparer old = comparer;
UKeyComparator UVector::setComparer(UKeyComparator d) {
UKeyComparator old = comparer;
comparer = d;
return old;
}
@ -163,7 +185,7 @@ UBool UVector::isOutOfMemory(void) {
void* UVector::orphanElementAt(int32_t index) {
void* e = 0;
if (0 <= index && index < count) {
e = elements[index];
e = elements[index].pointer;
for (int32_t i=index; i<count-1; ++i) {
elements[i] = elements[i+1];
}
@ -177,16 +199,28 @@ UStack::UStack(int32_t initialCapacity) :
UVector(initialCapacity) {
}
UStack::UStack(Deleter d, Comparer c, int32_t initialCapacity) :
UStack::UStack(UObjectDeleter d, UKeyComparator c, int32_t initialCapacity) :
UVector(d, c, initialCapacity) {
}
void* UStack::pop(void) {
void* obj = lastElement();
if (obj != 0) {
removeElementAt(size() - 1);
int32_t n = size() - 1;
void* result = 0;
if (n >= 0) {
result = elementAt(n);
removeElementAt(n);
}
return obj;
return result;
}
int32_t UStack::popi(void) {
int32_t n = size() - 1;
int32_t result = 0;
if (n >= 0) {
result = elementAti(n);
removeElementAt(n);
}
return result;
}
int32_t UStack::search(void* obj) const {

View File

@ -13,6 +13,7 @@
#define UVECTOR_H
#include "unicode/utypes.h"
#include "uhash.h"
/**
* <p>Ultralightweight C++ implementation of a <tt>void*</tt> vector
@ -65,27 +66,30 @@
* @author Alan Liu
*/
class U_COMMON_API UVector {
public:
typedef void (* U_CALLCONV Deleter)(void*);
typedef UBool (* U_CALLCONV Comparer)(const void*, const void*);
// NOTE: UVector uses the UHashKey (union of void* and int32_t) as
// its basic storage type. It uses UKeyComparator as its
// comparison function. It uses UObjectDeleter as its deleter
// function. These are named for hashtables, but used here as-is
// rather than duplicating the type. This allows sharing of
// support functions.
private:
int32_t count;
int32_t capacity;
void** elements;
UHashKey* elements;
Deleter deleter;
UObjectDeleter deleter;
Comparer comparer;
UKeyComparator comparer;
static UBool outOfMemory;
public:
UVector(int32_t initialCapacity = 8);
UVector(Deleter d, Comparer c, int32_t initialCapacity = 8);
UVector(UObjectDeleter d, UKeyComparator c, int32_t initialCapacity = 8);
~UVector();
@ -95,12 +99,18 @@ public:
void addElement(void* obj);
void addElement(int32_t elem);
void setElementAt(void* obj, int32_t index);
void setElementAt(int32_t elem, int32_t index);
void insertElementAt(void* obj, int32_t index);
void* elementAt(int32_t index) const;
int32_t elementAti(int32_t index) const;
void* firstElement(void) const;
void* lastElement(void) const;
@ -125,9 +135,9 @@ public:
// New API
//------------------------------------------------------------
Deleter setDeleter(Deleter d);
UObjectDeleter setDeleter(UObjectDeleter d);
Comparer setComparer(Comparer c);
UKeyComparator setComparer(UKeyComparator c);
static UBool isOutOfMemory(void);
@ -175,7 +185,7 @@ class U_COMMON_API UStack : public UVector {
public:
UStack(int32_t initialCapacity = 8);
UStack(Deleter d, Comparer c, int32_t initialCapacity = 8);
UStack(UObjectDeleter d, UKeyComparator c, int32_t initialCapacity = 8);
// It's okay not to have a virtual destructor (in UVector)
// because UStack has no special cleanup to do.
@ -186,8 +196,12 @@ public:
void* pop(void);
int32_t popi(void);
void* push(void* obj);
int32_t push(int32_t i);
int32_t search(void* obj) const;
private:
@ -240,4 +254,9 @@ inline void* UStack::push(void* obj) {
return obj;
}
inline int32_t UStack::push(int32_t i) {
addElement(i);
return i;
}
#endif

View File

@ -160,24 +160,12 @@ private:
int32_t size() const; // size of the UVectors
};
// Store int32_t as a void* in a UVector. DO NOT ASSUME sizeof(void*)
// is 32. Assume sizeof(void*) >= 32.
inline void* _int32_to_voidPtr(int32_t x) {
void* a = 0; // May be > 32 bits
*(int32_t*)&a = x; // Careful here...
return a;
}
inline int32_t _voidPtr_to_int32(void* x) {
void* a = x; // Copy to stack (portability)
return *(int32_t*)&a; // Careful here...
}
int32_t Segments::offset(int32_t i) const {
return _voidPtr_to_int32(offsets.elementAt(i));
return offsets.elementAti(i);
}
UBool Segments::isOpen(int32_t i) const {
return _voidPtr_to_int32(isOpenParen.elementAt(i)) != 0;
return isOpenParen.elementAti(i) != 0;
}
int32_t Segments::size() const {
@ -189,8 +177,8 @@ Segments::Segments() {}
Segments::~Segments() {}
void Segments::addParenthesisAt(int32_t offset, UBool isOpen) {
offsets.addElement(_int32_to_voidPtr(offset));
isOpenParen.addElement(_int32_to_voidPtr(isOpen ? 1 : 0));
offsets.addElement(offset);
isOpenParen.addElement(isOpen ? 1 : 0);
}
int32_t Segments::getLastParenOffset(UBool& isOpenParen) const {
@ -226,7 +214,7 @@ UBool Segments::extractLastParenSubstring(int32_t& start, int32_t& limit) {
// Reset all segment pairs from i to size() - 1 to [start, start+1).
while (i<size()) {
int32_t o = isOpen(i) ? start : (start+1);
offsets.setElementAt(_int32_to_voidPtr(o), i);
offsets.setElementAt(o, i);
++i;
}
return TRUE;
@ -301,10 +289,10 @@ int32_t* Segments::createArray() const {
// Close parens are at 2*seg+1 in array 2.
if (open) {
array[a2offset + 2*nextOpen] = 2+i;
stack.push(_int32_to_voidPtr(nextOpen));
stack.push(nextOpen);
++nextOpen;
} else {
int32_t nextClose = _voidPtr_to_int32(stack.pop());
int32_t nextClose = stack.popi();
array[a2offset + 2*nextClose+1] = 2+i;
}
}

View File

@ -1475,22 +1475,6 @@ UChar Transliterator::filteredCharAt(const Replaceable& text, int32_t i) const {
(localFilter->contains(c = text.charAt(i)) ? c : (UChar)0xFFFE);
}
/**
* Comparison function for UVector.
*
* Do not make this a class static: This should remain a C function
* for os/390 and Solaris Workshop [grhoten]
*/
U_CDECL_BEGIN
static UBool U_CALLCONV
_compareCaselessUnicodeString(const void* a, const void* b) {
UHashKey s, t;
s.pointer = (void*) a;
t.pointer = (void*) b;
return uhash_compareCaselessUnicodeString(s, t);
}
U_CDECL_END
void Transliterator::initializeCache(void) {
// Lock first, check init boolean second
Mutex lock(&cacheMutex);
@ -1504,7 +1488,7 @@ void Transliterator::initializeCache(void) {
// That way if the resource is absent, we will at least
// have a valid cache object.
cacheIDs.setDeleter(uhash_deleteUnicodeString);
cacheIDs.setComparer(_compareCaselessUnicodeString);
cacheIDs.setComparer(uhash_compareCaselessUnicodeString);
/* The following code parses the index table located in
* icu/data/translit_index.txt. The index is an n x 4 table