ICU-551.24.tar.gz
[apple/icu.git] / icuSources / common / rbbitblb.cpp
index 6bc60c2ddc1a806e068518986490eb7353b2d87f..01b1c4cba070d3d7bc8e268932d13027e20a3b31 100644 (file)
@@ -1,6 +1,6 @@
 /*
 **********************************************************************
-*   Copyright (c) 2002-2006, International Business Machines
+*   Copyright (c) 2002-2009, International Business Machines
 *   Corporation and others.  All Rights Reserved.
 **********************************************************************
 */
@@ -92,6 +92,13 @@ void  RBBITableBuilder::build() {
     if (fRB->fSetBuilder->sawBOF()) {
         RBBINode *bofTop    = new RBBINode(RBBINode::opCat);
         RBBINode *bofLeaf   = new RBBINode(RBBINode::leafChar);
+        // Delete and exit if memory allocation failed.
+        if (bofTop == NULL || bofLeaf == NULL) {
+            *fStatus = U_MEMORY_ALLOCATION_ERROR;
+            delete bofTop;
+            delete bofLeaf;
+            return;
+        }
         bofTop->fLeftChild  = bofLeaf;
         bofTop->fRightChild = fTree;
         bofLeaf->fParent    = bofTop;
@@ -105,9 +112,20 @@ void  RBBITableBuilder::build() {
     //   right child being the end marker.
     //
     RBBINode *cn = new RBBINode(RBBINode::opCat);
+    // Exit if memory allocation failed.
+    if (cn == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+        return;
+    }
     cn->fLeftChild = fTree;
     fTree->fParent = cn;
     cn->fRightChild = new RBBINode(RBBINode::endMark);
+    // Delete and exit if memory allocation failed.
+    if (cn->fRightChild == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+        delete cn;
+        return;
+    }
     cn->fRightChild->fParent = cn;
     fTree = cn;
 
@@ -422,13 +440,21 @@ void RBBITableBuilder::calcChainedFollowPos(RBBINode *tree) {
         //                            don't chain from it.
         // TODO:  Add rule syntax for this behavior, get specifics out of here and
         //        into the rule file.
-        if (fRB->fLBCMNoChain) {
+        if (fRB->fLBCMNoChain || fRB->fRINoChain) {
             UChar32 c = this->fRB->fSetBuilder->getFirstChar(endNode->fVal);
             if (c != -1) {
                 // c == -1 occurs with sets containing only the {eof} marker string.
-                ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
-                if (cLBProp == U_LB_COMBINING_MARK) {
-                    continue;
+                if (fRB->fLBCMNoChain) {
+                    ULineBreak cLBProp = (ULineBreak)u_getIntPropertyValue(c, UCHAR_LINE_BREAK);
+                    if (cLBProp == U_LB_COMBINING_MARK) {
+                        continue;
+                    }
+                }
+                if (fRB->fRINoChain) {
+                    UGraphemeClusterBreak cGBProp = (UGraphemeClusterBreak)u_getIntPropertyValue(c, UCHAR_GRAPHEME_CLUSTER_BREAK);
+                    if (cGBProp == U_GCB_REGIONAL_INDICATOR) {
+                        continue;
+                    }
                 }
             }
         }
@@ -527,33 +553,49 @@ void RBBITableBuilder::buildStateTable() {
     if (U_FAILURE(*fStatus)) {
         return;
     }
+    RBBIStateDescriptor *failState;
+    // Set it to NULL to avoid uninitialized warning
+    RBBIStateDescriptor *initialState = NULL; 
     //
     // Add a dummy state 0 - the stop state.  Not from Aho.
     int      lastInputSymbol = fRB->fSetBuilder->getNumCharCategories() - 1;
-    RBBIStateDescriptor *failState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+    failState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+    if (failState == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+        goto ExitBuildSTdeleteall;
+    }
     failState->fPositions = new UVector(*fStatus);
-    if (U_FAILURE(*fStatus)) {
-        return;
+    if (failState->fPositions == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+    }
+    if (failState->fPositions == NULL || U_FAILURE(*fStatus)) {
+        goto ExitBuildSTdeleteall;
     }
     fDStates->addElement(failState, *fStatus);
     if (U_FAILURE(*fStatus)) {
-        return;
+        goto ExitBuildSTdeleteall;
     }
 
     // initially, the only unmarked state in Dstates is firstpos(root),
     //       where toot is the root of the syntax tree for (r)#;
-    RBBIStateDescriptor *initialState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+    initialState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+    if (initialState == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+    }
     if (U_FAILURE(*fStatus)) {
-        return;
+        goto ExitBuildSTdeleteall;
     }
     initialState->fPositions = new UVector(*fStatus);
+    if (initialState->fPositions == NULL) {
+        *fStatus = U_MEMORY_ALLOCATION_ERROR;
+    }
     if (U_FAILURE(*fStatus)) {
-        return;
+        goto ExitBuildSTdeleteall;
     }
     setAdd(initialState->fPositions, fTree->fFirstPosSet);
     fDStates->addElement(initialState, *fStatus);
     if (U_FAILURE(*fStatus)) {
-        return;
+        goto ExitBuildSTdeleteall;
     }
 
     // while there is an unmarked state T in Dstates do begin
@@ -589,6 +631,10 @@ void RBBITableBuilder::buildStateTable() {
                 if ((p->fType == RBBINode::leafChar) &&  (p->fVal == a)) {
                     if (U == NULL) {
                         U = new UVector(*fStatus);
+                        if (U == NULL) {
+                               *fStatus = U_MEMORY_ALLOCATION_ERROR;
+                               goto ExitBuildSTdeleteall;
+                        }
                     }
                     setAdd(U, p->fFollowPos);
                 }
@@ -616,8 +662,11 @@ void RBBITableBuilder::buildStateTable() {
                 if (!UinDstates)
                 {
                     RBBIStateDescriptor *newState = new RBBIStateDescriptor(lastInputSymbol, fStatus);
+                    if (newState == NULL) {
+                       *fStatus = U_MEMORY_ALLOCATION_ERROR;
+                    }
                     if (U_FAILURE(*fStatus)) {
-                        return;
+                        goto ExitBuildSTdeleteall;
                     }
                     newState->fPositions = U;
                     fDStates->addElement(newState, *fStatus);
@@ -632,6 +681,11 @@ void RBBITableBuilder::buildStateTable() {
             }
         }
     }
+    return;
+    // delete local pointers only if error occured.
+ExitBuildSTdeleteall:
+    delete initialState;
+    delete failState;
 }
 
 
@@ -906,75 +960,59 @@ void RBBITableBuilder::sortedAdd(UVector **vector, int32_t val) {
 //
 //-----------------------------------------------------------------------------
 void RBBITableBuilder::setAdd(UVector *dest, UVector *source) {
-    int destOriginalSize = dest->size();
-    int sourceSize       = source->size();
+    int32_t destOriginalSize = dest->size();
+    int32_t sourceSize       = source->size();
     int32_t di           = 0;
-    void *(destS[16]), *(sourceS[16]);  // Handle small cases without malloc
-    void **destH = 0, **sourceH = 0;
-    void **destBuff, **sourceBuff;
+    MaybeStackArray<void *, 16> destArray, sourceArray;  // Handle small cases without malloc
+    void **destPtr, **sourcePtr;
     void **destLim, **sourceLim;
 
-    if (destOriginalSize > sizeof(destS)/sizeof(destS[0])) {
-        destH = (void **)uprv_malloc(sizeof(void *) * destOriginalSize);
-        destBuff = destH;
-    }
-    else {
-        destBuff = destS;
-    }
-    if (destBuff == 0) {
-        return;
+    if (destOriginalSize > destArray.getCapacity()) {
+        if (destArray.resize(destOriginalSize) == NULL) {
+            return;
+        }
     }
-    destLim = destBuff + destOriginalSize;
+    destPtr = destArray.getAlias();
+    destLim = destPtr + destOriginalSize;  // destArray.getArrayLimit()?
 
-    if (sourceSize > sizeof(sourceS)/sizeof(sourceS[0])) {
-        sourceH = (void **)uprv_malloc(sizeof(void *) * sourceSize);
-        sourceBuff = sourceH;
-    }
-    else {
-        sourceBuff = sourceS;
-    }
-    if (sourceBuff == 0) {
-        if (destH) {
-            uprv_free(destH);
+    if (sourceSize > sourceArray.getCapacity()) {
+        if (sourceArray.resize(sourceSize) == NULL) {
+            return;
         }
-        return;
     }
-    sourceLim = sourceBuff + sourceSize;
+    sourcePtr = sourceArray.getAlias();
+    sourceLim = sourcePtr + sourceSize;  // sourceArray.getArrayLimit()?
 
     // Avoid multiple "get element" calls by getting the contents into arrays
-    (void) dest->toArray(destBuff);
-    (void) source->toArray(sourceBuff);
+    (void) dest->toArray(destPtr);
+    (void) source->toArray(sourcePtr);
 
-    dest->setSize(sourceSize+destOriginalSize);
+    dest->setSize(sourceSize+destOriginalSize, *fStatus);
 
-    while (sourceBuff < sourceLim && destBuff < destLim) {
-        if (*destBuff < *sourceBuff) {
-            dest->setElementAt(*destBuff++, di++);
+    while (sourcePtr < sourceLim && destPtr < destLim) {
+        if (*destPtr == *sourcePtr) {
+            dest->setElementAt(*sourcePtr++, di++);
+            destPtr++;
         }
-        else if (*sourceBuff < *destBuff) {
-            dest->setElementAt(*sourceBuff++, di++);
+        // This check is required for machines with segmented memory, like i5/OS.
+        // Direct pointer comparison is not recommended.
+        else if (uprv_memcmp(destPtr, sourcePtr, sizeof(void *)) < 0) {
+            dest->setElementAt(*destPtr++, di++);
         }
-        else {
-            dest->setElementAt(*sourceBuff++, di++);
-            destBuff++;
+        else { /* *sourcePtr < *destPtr */
+            dest->setElementAt(*sourcePtr++, di++);
         }
     }
 
     // At most one of these two cleanup loops will execute
-    while (destBuff < destLim) {
-        dest->setElementAt(*destBuff++, di++);
+    while (destPtr < destLim) {
+        dest->setElementAt(*destPtr++, di++);
     }
-    while (sourceBuff < sourceLim) {
-        dest->setElementAt(*sourceBuff++, di++);
+    while (sourcePtr < sourceLim) {
+        dest->setElementAt(*sourcePtr++, di++);
     }
 
-    dest->setSize(di);
-    if (destH) {
-        uprv_free(destH);
-    }
-    if (sourceH) {
-        uprv_free(sourceH);
-    }
+    dest->setSize(di, *fStatus);
 }
 
 
@@ -1209,7 +1247,7 @@ RBBIStateDescriptor::RBBIStateDescriptor(int lastInputSymbol, UErrorCode *fStatu
         *fStatus = U_MEMORY_ALLOCATION_ERROR;
         return;
     }
-    fDtran->setSize(lastInputSymbol+1);    // fDtran needs to be pre-sized.
+    fDtran->setSize(lastInputSymbol+1, *fStatus);    // fDtran needs to be pre-sized.
                                            //   It is indexed by input symbols, and will
                                            //   hold  the next state number for each
                                            //   symbol.