/*
**********************************************************************
-* Copyright (C) 1999-2001 IBM Corp. All rights reserved.
+* Copyright (C) 1999-2004 IBM Corp. All rights reserved.
**********************************************************************
* Date Name Description
* 12/1/99 rgillam Complete port from Java.
#include "dbbi_tbl.h"
#include "uvector.h"
#include "cmemory.h"
+#include "uassert.h"
U_NAMESPACE_BEGIN
-const char DictionaryBasedBreakIterator::fgClassID = 0;
+UOBJECT_DEFINE_RTTI_IMPLEMENTATION(DictionaryBasedBreakIterator)
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// constructors
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
DictionaryBasedBreakIterator::DictionaryBasedBreakIterator() :
RuleBasedBreakIterator() {
init();
if (U_FAILURE(status)) {return;};
fTables = new DictionaryBasedBreakIteratorTables(dictionaryFilename, status);
+ if (U_FAILURE(status)) {
+ if (fTables != NULL) {
+ fTables->removeReference();
+ fTables = NULL;
+ }
+ return;
+ }
/* test for NULL */
if(fTables == 0) {
status = U_MEMORY_ALLOCATION_ERROR;
return;
}
-
- if (U_FAILURE(status)) {
- fTables->removeReference();
- fTables = NULL;
- return;
- }
}
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// Destructor
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
DictionaryBasedBreakIterator::~DictionaryBasedBreakIterator()
{
uprv_free(cachedBreakPositions);
if (fTables != NULL) {fTables->removeReference();};
}
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// Assignment operator. Sets this iterator to have the same behavior,
// and iterate over the same text, as the one passed in.
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
DictionaryBasedBreakIterator&
DictionaryBasedBreakIterator::operator=(const DictionaryBasedBreakIterator& that) {
if (this == &that) {
return *this;
}
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// Clone() Returns a newly-constructed RuleBasedBreakIterator with the same
// behavior, and iterating over the same text, as this one.
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
BreakIterator*
DictionaryBasedBreakIterator::clone() const {
return new DictionaryBasedBreakIterator(*this);
reset();
int32_t result = RuleBasedBreakIterator::previous();
if (cachedBreakPositions != NULL) {
- positionInCache = numCachedBreakPositions - 2;
+ for (positionInCache=0;
+ cachedBreakPositions[positionInCache] != result;
+ positionInCache++);
+ U_ASSERT(positionInCache < numCachedBreakPositions);
+ if (positionInCache >= numCachedBreakPositions) {
+ // Something has gone wrong. Dump the cache.
+ reset();
+ }
}
return result;
}
// for the new range
if (fDictionaryCharCount > 1 && result - startPos > 1) {
divideUpDictionaryRange(startPos, result, status);
+ U_ASSERT(U_SUCCESS(status));
if (U_FAILURE(status)) {
- return -9999; // SHOULD NEVER GET HERE!
+ // Something went badly wrong, an internal error.
+ // We have no way from here to report it to caller.
+ // Treat as if this is if the dictionary did not apply to range.
+ reset();
+ return result;
}
}
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// init() Common initialization routine, for use by constructors, etc.
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
void DictionaryBasedBreakIterator::init() {
cachedBreakPositions = NULL;
fTables = NULL;
}
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
//
// BufferClone
//
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
BreakIterator * DictionaryBasedBreakIterator::createBufferClone(void *stackBuffer,
int32_t &bufferSize,
UErrorCode &status)
c = fText->next();
}
+ if (U_FAILURE(status)) {
+ return; // UStack below overwrites the status error codes
+ }
// initialize. We maintain two stacks: currentBreakPositions contains
// the list of break positions that will be returned if we successfully
// further, this saves us from having to follow each possible path
// through the text all the way to the error (hopefully avoiding many
// future recursive calls as well).
- UStack currentBreakPositions(status);
+ // there can be only one kind of error in UStack and UVector, so we'll
+ // just let the error fall through
+ UStack currentBreakPositions(status);
UStack possibleBreakPositions(status);
UVector wrongBreakPositions(status);
// the possible-break-positions stack
if (fTables->fDictionary->at(state, (int32_t)0) == -1) {
possibleBreakPositions.push(fText->getIndex(), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
}
// look up the new state to transition to in the dictionary
// of the loop.
if (state == -1) {
currentBreakPositions.push(fText->getIndex(), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
break;
}
currentBreakPositions.removeAllElements();
for (int32_t i = 0; i < bestBreakPositions.size(); i++) {
currentBreakPositions.push(bestBreakPositions.elementAti(i), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
}
bestBreakPositions.removeAllElements();
if (farthestEndPoint < endPos) {
|| currentBreakPositions.peeki() != fText->getIndex())
&& fText->getIndex() != startPos) {
currentBreakPositions.push(fText->getIndex(), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
}
fText->next();
currentBreakPositions.push(fText->getIndex(), status);
+ if (U_FAILURE(status)) {
+ return;
+ }
}
}
currentBreakPositions.popi();
}
currentBreakPositions.push(endPos, status);
+ if (U_FAILURE(status)) {
+ return;
+ }
// create a regular array to hold the break positions and copy
// the break positions from the stack to the array (in addition,