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:
parent
d6407cb579
commit
5244af4879
@ -187,6 +187,7 @@ BreakIterator::getDisplayName(const Locale& objectLocale,
|
||||
|
||||
BreakIterator::BreakIterator()
|
||||
{
|
||||
fBufferClone = FALSE;
|
||||
}
|
||||
|
||||
BreakIterator::~BreakIterator()
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 {
|
||||
|
Loading…
Reference in New Issue
Block a user