X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/73c04bcfe1096173b00431f0cdc742894b15eef0..b331163bffd790ced0e88b73f44f86d49ccc48a5:/icuSources/common/rbbitblb.cpp?ds=inline diff --git a/icuSources/common/rbbitblb.cpp b/icuSources/common/rbbitblb.cpp index 6bc60c2d..01b1c4cb 100644 --- a/icuSources/common/rbbitblb.cpp +++ b/icuSources/common/rbbitblb.cpp @@ -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 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.