]> git.saurik.com Git - apple/icu.git/blobdiff - icuSources/common/dbbi.cpp
ICU-6.2.10.tar.gz
[apple/icu.git] / icuSources / common / dbbi.cpp
index def45650022bf365d765ca1929bc3b03231667f2..2f83f6c3e39932cce5441f05431bbc8041dde709 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   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() {
@@ -43,17 +44,18 @@ DictionaryBasedBreakIterator::DictionaryBasedBreakIterator(UDataMemory* rbbiData
     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;
-    }
 }
 
 
@@ -70,11 +72,11 @@ RuleBasedBreakIterator(other)
 
 
 
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //   Destructor
 //
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 DictionaryBasedBreakIterator::~DictionaryBasedBreakIterator()
 {
     uprv_free(cachedBreakPositions);
@@ -82,12 +84,12 @@ DictionaryBasedBreakIterator::~DictionaryBasedBreakIterator()
     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) {
@@ -103,12 +105,12 @@ DictionaryBasedBreakIterator::operator=(const DictionaryBasedBreakIterator& 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);
@@ -141,7 +143,14 @@ DictionaryBasedBreakIterator::previous()
         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;
     }
@@ -256,8 +265,13 @@ DictionaryBasedBreakIterator::handleNext()
         // 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;
             }
         }
 
@@ -292,11 +306,11 @@ DictionaryBasedBreakIterator::reset()
 
 
 
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //    init()    Common initialization routine, for use by constructors, etc.
 //
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 void DictionaryBasedBreakIterator::init() {
     cachedBreakPositions    = NULL;
     fTables                 = NULL;
@@ -306,11 +320,11 @@ void DictionaryBasedBreakIterator::init() {
 }
 
 
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 //
 //    BufferClone
 //
-//-------------------------------------------------------------------------------
+//------------------------------------------------------------------------------
 BreakIterator *  DictionaryBasedBreakIterator::createBufferClone(void *stackBuffer,
                                    int32_t &bufferSize,
                                    UErrorCode &status)
@@ -396,6 +410,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
         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
@@ -412,7 +429,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
     // 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);
 
@@ -445,6 +464,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
         // 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
@@ -456,6 +478,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
         // of the loop.
         if (state == -1) {
             currentBreakPositions.push(fText->getIndex(), status);
+            if (U_FAILURE(status)) {
+                return;
+            }
             break;
         }
 
@@ -501,6 +526,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
                     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) {
@@ -515,9 +543,15 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
                             || 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;
+                    }
                 }
             }
 
@@ -561,6 +595,9 @@ DictionaryBasedBreakIterator::divideUpDictionaryRange(int32_t startPos, int32_t
         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,