ICU-853 Implementations for ubrk_safeClone, including C++ API changes needed (createBufferClone & isBufferClone in BreakIterator classes)

X-SVN-Rev: 3713
This commit is contained in:
Jim Snyder Grant 2001-02-21 23:40:41 +00:00
parent d6407cb579
commit 5244af4879
7 changed files with 238 additions and 4 deletions

View File

@ -187,6 +187,7 @@ BreakIterator::getDisplayName(const Locale& objectLocale,
BreakIterator::BreakIterator()
{
fBufferClone = FALSE;
}
BreakIterator::~BreakIterator()

View File

@ -12,6 +12,7 @@
#include "unicode/dbbi.h"
#include "dbbi_tbl.h"
#include "uvector.h"
#include "unicode/schriter.h"
char DictionaryBasedBreakIterator::fgClassID = 0;
@ -240,6 +241,101 @@ DictionaryBasedBreakIterator::reset()
positionInCache = 0;
}
// internal type for BufferClone
struct bufferCloneStructUChar
{
DictionaryBasedBreakIterator bi;
UCharCharacterIterator text;
};
struct bufferCloneStructString
{
DictionaryBasedBreakIterator bi;
StringCharacterIterator text;
};
BreakIterator * DictionaryBasedBreakIterator::createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status)
{
DictionaryBasedBreakIterator * localIterator;
int32_t bufferSizeNeeded;
UBool IterIsUChar;
UBool IterIsString;
if (U_FAILURE(status)){
return 0;
}
if (!this){
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
if (text == NULL)
{
bufferSizeNeeded = sizeof(DictionaryBasedBreakIterator);
IterIsString = IterIsUChar = FALSE;
}
else if (text->getDynamicClassID() == StringCharacterIterator::getStaticClassID())
{
bufferSizeNeeded = sizeof(struct bufferCloneStructString);
IterIsString = TRUE;
IterIsUChar = FALSE;
}
else if (text->getDynamicClassID() == UCharCharacterIterator::getStaticClassID())
{
bufferSizeNeeded = sizeof(struct bufferCloneStructUChar);
IterIsString = FALSE;
IterIsUChar = TRUE;
}
else
{
// code has changed - time to make a real CharacterIterator::CreateBufferClone()
}
if (BufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
BufferSize = bufferSizeNeeded;
return 0;
}
if (BufferSize < bufferSizeNeeded || !stackBuffer)
{
/* allocate one here...*/
localIterator = new DictionaryBasedBreakIterator(*this);
status = U_SAFECLONE_ALLOCATED_ERROR;
return localIterator;
}
if (IterIsUChar) {
struct bufferCloneStructUChar * localClone
= (struct bufferCloneStructUChar *)stackBuffer;
localIterator = &localClone->bi;
memcpy(localIterator, this, sizeof(DictionaryBasedBreakIterator));
memcpy(&localClone->text, text, sizeof(UCharCharacterIterator));
localClone->text = *(UCharCharacterIterator*)text;
localIterator->text = &localClone->text;
} else if (IterIsString) {
struct bufferCloneStructString * localClone
= (struct bufferCloneStructString *)stackBuffer;
localIterator = &localClone->bi;
memcpy(localIterator, this, sizeof(DictionaryBasedBreakIterator));
memcpy(&localClone->text, text, sizeof(StringCharacterIterator));
localClone->text = *(StringCharacterIterator*)text;
localIterator->text = &localClone->text;
} else {
DictionaryBasedBreakIterator * localClone
= (DictionaryBasedBreakIterator *)stackBuffer;
localIterator = localClone;
memcpy(localIterator, this, sizeof(DictionaryBasedBreakIterator));
}
// must not use the old cache if it exists - not threadsafe
localIterator->fBufferClone = TRUE;
localIterator->cachedBreakPositions = NULL;
localIterator->numCachedBreakPositions = 0;
localIterator->positionInCache = 0;
return localIterator;
}
/**
* This is the function that actually implements the dictionary-based
* algorithm. Given the endpoints of a range of text, it uses the

View File

@ -560,3 +560,91 @@ RuleBasedBreakIterator::reset()
// Base-class version of this function is a no-op.
// Subclasses may override with their own reset behavior.
}
// internal type for BufferClone
struct bufferCloneStructUChar
{
RuleBasedBreakIterator bi;
UCharCharacterIterator text;
};
struct bufferCloneStructString
{
RuleBasedBreakIterator bi;
StringCharacterIterator text;
};
BreakIterator * RuleBasedBreakIterator::createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status)
{
RuleBasedBreakIterator * localIterator;
int32_t bufferSizeNeeded;
UBool IterIsUChar;
UBool IterIsString;
if (U_FAILURE(status)){
return 0;
}
if (!this){
status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
if (text == NULL)
{
bufferSizeNeeded = sizeof(RuleBasedBreakIterator);
IterIsString = IterIsUChar = FALSE;
}
else if (text->getDynamicClassID() == StringCharacterIterator::getStaticClassID())
{
bufferSizeNeeded = sizeof(struct bufferCloneStructString);
IterIsString = TRUE;
IterIsUChar = FALSE;
}
else if (text->getDynamicClassID() == UCharCharacterIterator::getStaticClassID())
{
bufferSizeNeeded = sizeof(struct bufferCloneStructUChar);
IterIsString = FALSE;
IterIsUChar = TRUE;
}
else
{
// code has changed - time to make a real CharacterIterator::CreateBufferClone()
}
if (BufferSize == 0){ /* 'preflighting' request - set needed size into *pBufferSize */
BufferSize = bufferSizeNeeded;
return 0;
}
if (BufferSize < bufferSizeNeeded || !stackBuffer)
{
/* allocate one here...*/
localIterator = new RuleBasedBreakIterator(*this);
status = U_SAFECLONE_ALLOCATED_ERROR;
} else if (IterIsUChar) {
struct bufferCloneStructUChar * localClone
= (struct bufferCloneStructUChar *)stackBuffer;
localIterator = &localClone->bi;
memcpy(localIterator, this, sizeof(RuleBasedBreakIterator));
memcpy(&localClone->text, text, sizeof(UCharCharacterIterator));
localClone->text = *(UCharCharacterIterator*)text;
localIterator->text = &localClone->text;
localIterator->fBufferClone = TRUE;
} else if (IterIsString) {
struct bufferCloneStructString * localClone
= (struct bufferCloneStructString *)stackBuffer;
localIterator = &localClone->bi;
memcpy(localIterator, this, sizeof(RuleBasedBreakIterator));
memcpy(&localClone->text, text, sizeof(StringCharacterIterator));
localClone->text = *(StringCharacterIterator*)text;
localIterator->text = &localClone->text;
localIterator->fBufferClone = TRUE;
} else {
RuleBasedBreakIterator * localClone
= (RuleBasedBreakIterator *)stackBuffer;
localIterator = localClone;
memcpy(localIterator, this, sizeof(RuleBasedBreakIterator));
localIterator->fBufferClone = TRUE;
}
return localIterator;
}

View File

@ -80,14 +80,24 @@ ubrk_safeClone(
int32_t *pBufferSize,
UErrorCode *status)
{
return 0; /* Hey! Add code here! */
if (status == NULL || U_FAILURE(*status)){
return 0;
}
if (!pBufferSize || !bi){
*status = U_ILLEGAL_ARGUMENT_ERROR;
return 0;
}
return (UBreakIterator *)(((BreakIterator*)bi)->
createBufferClone(stackBuffer, *pBufferSize, *status));
}
U_CAPI void
ubrk_close(UBreakIterator *bi)
{
delete (BreakIterator*) bi;
if (!((BreakIterator*) bi)->isBufferClone())
{
delete (BreakIterator*) bi;
}
}
U_CAPI void

View File

@ -449,11 +449,33 @@ public:
static UnicodeString& getDisplayName(const Locale& objectLocale,
UnicodeString& name);
/**
* Thread safe client-buffer-based cloning operation
* Do NOT call delete on a safeclone, since 'new' is not used to create it.
* @param stackBuffer user allocated space for the new clone. If NULL new memory will be allocated.
If buffer is not large enough, new memory will be allocated.
* @param BufferSize reference to size of allocated space.
If BufferSize == 0, a sufficient size for use in cloning will
be returned ('pre-flighting')
If BufferSize is not enough for a stack-based safe clone,
new memory will be allocated.
* @param status to indicate whether the operation went on smoothly or there were errors
An informational status value, U_SAFECLONE_ALLOCATED_ERROR, is used if any allocations were
necessary.
* @return pointer to the new clone
*
* @draft API 1.8 freeze
*/
virtual BreakIterator * createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status) = 0;
inline UBool isBufferClone(void);
protected:
BreakIterator();
UBool fBufferClone;
private:
/**
* The copy constructor and assignment operator have no real implementation.
@ -463,5 +485,11 @@ private:
BreakIterator (const BreakIterator&) {}
};
inline UBool BreakIterator::isBufferClone()
{
return fBufferClone;
}
#endif // _BRKITER
//eof

View File

@ -183,6 +183,11 @@ protected:
*/
virtual void reset(void);
virtual BreakIterator * createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status);
private:
/**
* This is the function that actually implements the dictionary-based

View File

@ -421,6 +421,11 @@ RuleBasedBreakIterator(UDataMemory* image);
*/
inline static UClassID getStaticClassID(void);
virtual BreakIterator * createBufferClone(void *stackBuffer,
int32_t &BufferSize,
UErrorCode &status);
protected:
//=======================================================================
// implementation
@ -459,6 +464,7 @@ private:
RuleBasedBreakIterator(RuleBasedBreakIteratorTables* adoptTables);
friend class BreakIterator;
};
inline UBool RuleBasedBreakIterator::operator!=(const BreakIterator& that) const {